Skip to content

Commit 2e46a1c

Browse files
committed
Merge remote-tracking branch 'h2database/master'
# Conflicts: # h2/src/docsrc/html/changelog.html
2 parents 5badbf9 + c0696ef commit 2e46a1c

File tree

14 files changed

+93
-30
lines changed

14 files changed

+93
-30
lines changed

h2/src/docsrc/html/advanced.html

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,12 +1526,16 @@ <h2 id="uuid">Universally Unique Identifiers (UUID)</h2>
15261526
<p>
15271527
This database supports UUIDs. Also supported is a function to create new UUIDs using
15281528
a cryptographically strong pseudo random number generator.
1529+
</p>
1530+
<p>
15291531
With random UUIDs, the chance of two having the same value can be calculated
15301532
using the probability theory. See also 'Birthday Paradox'.
1531-
Standardized randomly generated UUIDs have 122 random bits.
1533+
</p>
1534+
<p>
1535+
RFC 9562-compliant randomly generated UUIDs with version 4 have 122 random bits.
15321536
4 bits are used for the version (Randomly generated UUID), and 2 bits for the variant (Leach-Salz).
1533-
This database supports generating such UUIDs using the built-in function
1534-
<code>RANDOM_UUID()</code> or <code>UUID()</code>.
1537+
This database supports generating such UUIDs using the built-in function <code>RANDOM_UUID(4)</code>.
1538+
Please note that indexes on UUIDs with this version may have a poor performance.
15351539
Here is a small program to estimate the probability of having two identical UUIDs
15361540
after generating a number of values:
15371541
</p>
@@ -1564,6 +1568,18 @@ <h2 id="uuid">Universally Unique Identifiers (UUID)</h2>
15641568
that means the probability is about 0.000'000'000'06.
15651569
</p>
15661570

1571+
<p>
1572+
RFC 9562-compliant time-ordered UUIDs with version 7 have layout optimized for database systems.
1573+
They contain 48-bit number of milliseconds seconds since midnight 1 Jan 1970 UTC with leap seconds excluded
1574+
and additional 12-bit sub-millisecond timestamp fraction plus 62 random bits or 74 random bits without this fraction
1575+
depending on implementation.
1576+
</p>
1577+
<p>
1578+
This database supports generating such UUIDs using the built-in function <code>RANDOM_UUID(7)</code>.
1579+
This function produces 12-bit sub-millisecond timestamp fraction if high resolution timestamps are available in JVM
1580+
and 62 pseudo random bits.
1581+
</p>
1582+
15671583
<h2 id="spatial_features">Spatial Features</h2>
15681584
<p>
15691585
H2 supports the geometry data type and spatial indexes.

h2/src/docsrc/html/changelog.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ <h2>Next Version (unreleased)</h2>
2727

2828
<h2>Version 2.3.232 (2024-08-11)</h2>
2929
<ul>
30+
<li>Issue #4005: Add optional version to RANDOM_UUID function and generator of version 7 in addition to existing version 4
31+
</li>
3032
<li>Issue #3945: Column not found in correlated subquery, when referencing outer column from LEFT JOIN .. ON clause
3133
</li>
3234
<li>Issue #4097: StackOverflowException when using multiple SELECT statements in one query (2.3.230)

h2/src/main/org/h2/command/Parser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4276,6 +4276,7 @@ private Expression readBuiltinFunctionIf(String upperName) {
42764276
case "SECURE_RAND":
42774277
return new RandFunction(readSingleArgument(), RandFunction.SECURE_RAND);
42784278
case "RANDOM_UUID":
4279+
return new RandFunction(readIfSingleArgument(), RandFunction.RANDOM_UUID);
42794280
case "UUID":
42804281
read(CLOSE_PAREN);
42814282
return new RandFunction(null, RandFunction.RANDOM_UUID);

h2/src/main/org/h2/expression/function/RandFunction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public Value getValue(SessionLocal session) {
7474
v = ValueVarbinary.getNoCopy(MathUtils.secureRandomBytes(v.getInt()));
7575
break;
7676
case RANDOM_UUID:
77-
v = ValueUuid.getNewRandom();
77+
v = ValueUuid.getNewRandom(v != null ? v.getInt() : 4);
7878
break;
7979
default:
8080
throw DbException.getInternalError("function=" + function);

h2/src/main/org/h2/mode/FunctionsMSSQLServer.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.h2.engine.SessionLocal;
1212
import org.h2.expression.Expression;
1313
import org.h2.expression.TypedValueExpression;
14+
import org.h2.expression.ValueExpression;
1415
import org.h2.expression.function.CoalesceFunction;
1516
import org.h2.expression.function.CurrentDateTimeValueFunction;
1617
import org.h2.expression.function.RandFunction;
@@ -19,6 +20,7 @@
1920
import org.h2.value.TypeInfo;
2021
import org.h2.value.Value;
2122
import org.h2.value.ValueBigint;
23+
import org.h2.value.ValueInteger;
2224
import org.h2.value.ValueNull;
2325

2426
/**
@@ -131,8 +133,18 @@ public Expression optimize(SessionLocal session) {
131133
case ISNULL:
132134
return new CoalesceFunction(CoalesceFunction.COALESCE, args).optimize(session);
133135
case NEWID:
136+
/*
137+
* MS SQL Server uses version 4.
138+
*/
139+
return new RandFunction(ValueExpression.get(ValueInteger.get(4)), RandFunction.RANDOM_UUID)
140+
.optimize(session);
134141
case NEWSEQUENTIALID:
135-
return new RandFunction(null, RandFunction.RANDOM_UUID).optimize(session);
142+
/*
143+
* MS SQL Server uses something non-standard, use standard version 7
144+
* instead.
145+
*/
146+
return new RandFunction(ValueExpression.get(ValueInteger.get(7)), RandFunction.RANDOM_UUID)
147+
.optimize(session);
136148
case SCOPE_IDENTITY:
137149
type = SCOPE_IDENTITY_TYPE;
138150
break;

h2/src/main/org/h2/mode/FunctionsOracle.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,9 @@ public final class FunctionsOracle extends ModeFunction {
3636
private static final HashMap<String, FunctionInfo> FUNCTIONS = new HashMap<>();
3737

3838
static {
39-
FUNCTIONS.put("ADD_MONTHS",
40-
new FunctionInfo("ADD_MONTHS", ADD_MONTHS, 2, Value.TIMESTAMP, true, true));
41-
FUNCTIONS.put("SYS_GUID",
42-
new FunctionInfo("SYS_GUID", SYS_GUID, 0, Value.VARBINARY, false, false));
43-
FUNCTIONS.put("TO_DATE",
44-
new FunctionInfo("TO_DATE", TO_DATE, VAR_ARGS, Value.TIMESTAMP, true, true));
39+
FUNCTIONS.put("ADD_MONTHS", new FunctionInfo("ADD_MONTHS", ADD_MONTHS, 2, Value.TIMESTAMP, true, true));
40+
FUNCTIONS.put("SYS_GUID", new FunctionInfo("SYS_GUID", SYS_GUID, 0, Value.VARBINARY, false, false));
41+
FUNCTIONS.put("TO_DATE", new FunctionInfo("TO_DATE", TO_DATE, VAR_ARGS, Value.TIMESTAMP, true, true));
4542
FUNCTIONS.put("TO_TIMESTAMP",
4643
new FunctionInfo("TO_TIMESTAMP", TO_TIMESTAMP, VAR_ARGS, Value.TIMESTAMP, true, true));
4744
FUNCTIONS.put("TO_TIMESTAMP_TZ",
@@ -115,7 +112,11 @@ public Value getValue(SessionLocal session) {
115112
result = DateTimeFunction.dateadd(session, DateTimeFunction.MONTH, v1.getInt(), v0);
116113
break;
117114
case SYS_GUID:
118-
result = ValueUuid.getNewRandom().convertTo(TypeInfo.TYPE_VARBINARY);
115+
/*
116+
* Oracle actually uses version 8 (vendor-specific). Standard
117+
* version 7 is more similar to it than default 4.
118+
*/
119+
result = ValueUuid.getNewRandom(7).convertTo(TypeInfo.TYPE_VARBINARY);
119120
break;
120121
case TO_DATE:
121122
result = ToDateParser.toDate(session, v0.getString(), v1 == null ? null : v1.getString());

h2/src/main/org/h2/mode/FunctionsPostgreSQL.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,11 @@ public Expression optimize(SessionLocal session) {
192192
return new CurrentGeneralValueSpecification(CurrentGeneralValueSpecification.CURRENT_CATALOG)
193193
.optimize(session);
194194
case GEN_RANDOM_UUID:
195-
return new RandFunction(null, RandFunction.RANDOM_UUID).optimize(session);
195+
/*
196+
* PostgresSQL uses version 4.
197+
*/
198+
return new RandFunction(ValueExpression.get(ValueInteger.get(4)), RandFunction.RANDOM_UUID)
199+
.optimize(session);
196200
default:
197201
boolean allConst = optimizeArguments(session);
198202
type = TypeInfo.getTypeInfo(info.returnDataType);

h2/src/main/org/h2/res/help.csv

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4611,7 +4611,7 @@ JSON
46114611
"Data Types","UUID Type","
46124612
@h2@ UUID
46134613
","
4614-
Universally unique identifier. This is a 128 bit value.
4614+
RFC 9562-compliant universally unique identifier. This is a 128 bit value.
46154615
To store values, use ""PreparedStatement.setBytes"",
46164616
""setString"", or ""setObject(uuid)"" (where ""uuid"" is a ""java.util.UUID"").
46174617
""ResultSet.getObject"" will return a ""java.util.UUID"".
@@ -4620,6 +4620,7 @@ Please note that using an index on randomly generated data will
46204620
result on poor performance once there are millions of rows in a table.
46214621
The reason is that the cache behavior is very bad with randomly distributed data.
46224622
This is a problem for any database system.
4623+
To avoid this problem use UUID version 7 values.
46234624

46244625
For details, see the documentation of ""java.util.UUID"".
46254626
","
@@ -5295,15 +5296,23 @@ RAND()
52955296
"
52965297

52975298
"Functions (Numeric)","RANDOM_UUID","
5298-
@h2@ { RANDOM_UUID | UUID } ()
5299+
@h2@ RANDOM_UUID([versionInt]) | UUID()
52995300
","
5300-
Returns a new UUID with 122 pseudo random bits.
5301+
Returns a new RFC 9562-compliant UUID with the specified version.
5302+
If version is not specified, a default version will be used.
5303+
Current default is 4, but it may be changed in future versions of H2.
53015304

5305+
Version 4 is a UUID with 122 pseudo random bits.
53025306
Please note that using an index on randomly generated data will
53035307
result on poor performance once there are millions of rows in a table.
53045308
The reason is that the cache behavior is very bad with randomly distributed data.
53055309
This is a problem for any database system.
5310+
5311+
Version 7 is a time-ordered UUID value with layout optimized for database systems.
5312+
It contains 48-bit number of milliseconds seconds since midnight 1 Jan 1970 UTC with leap seconds excluded,
5313+
additional 12-bit sub-millisecond timestamp fraction if available, and 62 pseudo random bits.
53065314
","
5315+
RANDOM_UUID(7)
53075316
RANDOM_UUID()
53085317
"
53095318

h2/src/main/org/h2/table/Column.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ public void initializeSequence(SessionLocal session, Schema schema, int id, bool
496496
String sequenceName;
497497
do {
498498
sequenceName = "SYSTEM_SEQUENCE_"
499-
+ StringUtils.toUpperEnglish(ValueUuid.getNewRandom().getString().replace('-', '_'));
499+
+ StringUtils.toUpperEnglish(ValueUuid.getNewRandom(4).getString().replace('-', '_'));
500500
} while (schema.findSequence(sequenceName) != null);
501501
identityOptions.setDataType(type);
502502
Sequence seq = new Sequence(session, schema, id, sequenceName, identityOptions, true);

h2/src/main/org/h2/util/StringUtils.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,12 @@
1010
import java.net.URLEncoder;
1111
import java.nio.charset.StandardCharsets;
1212
import java.text.Collator;
13-
import java.text.Normalizer;
1413
import java.util.ArrayList;
1514
import java.util.Arrays;
1615
import java.util.HashSet;
1716
import java.util.Locale;
1817
import java.util.concurrent.TimeUnit;
1918
import java.util.function.IntPredicate;
20-
import java.util.regex.Matcher;
21-
import java.util.regex.Pattern;
2219

2320
import org.h2.api.ErrorCode;
2421
import org.h2.engine.SysProperties;

0 commit comments

Comments
 (0)