diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java
index 4fd1c0b67f67..a3b913160172 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java
@@ -24,6 +24,8 @@
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitOffsetLimitHandler;
import org.hibernate.dialect.sql.ast.SpannerSqlAstTranslator;
+import org.hibernate.dialect.temptable.SpannerTemporaryTableExporter;
+import org.hibernate.dialect.temptable.TemporaryTableExporter;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
@@ -99,6 +101,9 @@ public class SpannerDialect extends Dialect {
private final Exporter
spannerTableExporter = new SpannerDialectTableExporter( this );
+ private final SpannerTemporaryTableExporter spannerTemporaryTableExporter = new SpannerTemporaryTableExporter(
+ this );
+
private static final LockingStrategy LOCKING_STRATEGY = new DoNothingLockingStrategy();
private static final EmptyExporter NOOP_EXPORTER = new EmptyExporter();
@@ -720,6 +725,11 @@ public String getAddPrimaryKeyConstraintString(String constraintName) {
throw new UnsupportedOperationException( "Cannot add primary key constraint in Cloud Spanner." );
}
+ @Override
+ public TemporaryTableExporter getTemporaryTableExporter() {
+ return spannerTemporaryTableExporter;
+ }
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Lock acquisition functions
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/temptable/SpannerTemporaryTableExporter.java b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/SpannerTemporaryTableExporter.java
new file mode 100644
index 000000000000..a5b625ea285e
--- /dev/null
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/temptable/SpannerTemporaryTableExporter.java
@@ -0,0 +1,78 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.dialect.temptable;
+
+import org.hibernate.dialect.SpannerDialect;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+/**
+ * Spanner-specific exporter for temporary tables.
+ * Spanner requires PRIMARY KEY definitions to be outside the column definition list.
+ * * Syntax: CREATE TABLE Name (Col Type) PRIMARY KEY (Col)
+ */
+public class SpannerTemporaryTableExporter extends StandardTemporaryTableExporter {
+
+ private final SpannerDialect dialect;
+
+ public SpannerTemporaryTableExporter(SpannerDialect dialect) {
+ super( dialect );
+ this.dialect = dialect;
+ }
+
+ @Override
+ public String getSqlCreateCommand(TemporaryTable temporaryTable) {
+ final StringBuilder buffer = new StringBuilder( dialect.getCreateTableString() )
+ .append( ' ' )
+ .append( temporaryTable.getQualifiedTableName() )
+ .append( " (" );
+ final List primaryKeyColumnNames = new ArrayList<>();
+ boolean first = true;
+ for ( TemporaryTableColumn column : temporaryTable.getColumnsForExport() ) {
+ if ( first ) {
+ first = false;
+ }
+ else {
+ buffer.append( ", " );
+ }
+ buffer.append( column.getColumnName() ).append( ' ' );
+ final String databaseTypeName = column.getSqlTypeDefinition();
+ buffer.append( databaseTypeName );
+ if ( !column.isNullable() ) {
+ buffer.append( " not null" );
+ }
+ // Track PK
+ if ( column.isPrimaryKey() ) {
+ primaryKeyColumnNames.add( column.getColumnName() );
+ }
+ }
+ buffer.append( ')' );
+ // append primary key (outside the column declaration for Spanner)
+ // primary key () is still needed even if there are no primary key columns
+ buffer.append( " primary key (" );
+ if ( !primaryKeyColumnNames.isEmpty() ) {
+ buffer.append( String.join( ", ", primaryKeyColumnNames ) );
+ }
+ buffer.append( ')' );
+ return buffer.toString();
+ }
+
+ @Override
+ public String getSqlTruncateCommand(
+ TemporaryTable temporaryTable,
+ Function sessionUidAccess,
+ SharedSessionContractImplementor session) {
+ if ( temporaryTable.getSessionUidColumn() != null ) {
+ return super.getSqlTruncateCommand( temporaryTable, sessionUidAccess, session );
+ }
+ else {
+ return dialect.getTruncateTableStatement( temporaryTable.getQualifiedTableName() );
+ }
+ }
+
+}