-
Notifications
You must be signed in to change notification settings - Fork 2.5k
[HUDI-3826] Make truncate partition use delete_partition operation #5272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
76a2f42
1cb81a9
0d6e6af
477b349
48161e5
de50fc1
9d25e9a
e42f8de
f3e859e
bc65d33
08f5f51
8bd6171
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,13 +29,13 @@ import org.apache.hudi.common.util.PartitionPathEncodeUtils | |
| import org.apache.hudi.{AvroConversionUtils, SparkAdapterSupport} | ||
| import org.apache.spark.api.java.JavaSparkContext | ||
| import org.apache.spark.sql.catalyst.TableIdentifier | ||
| import org.apache.spark.sql.catalyst.analysis.{Resolver, UnresolvedRelation} | ||
| import org.apache.spark.sql.catalyst.catalog.{CatalogTable, CatalogTableType, HoodieCatalogTable} | ||
| import org.apache.spark.sql.catalyst.analysis.Resolver | ||
| import org.apache.spark.sql.catalyst.catalog.CatalogTypes.TablePartitionSpec | ||
| import org.apache.spark.sql.catalyst.catalog.{CatalogTable, HoodieCatalogTable} | ||
| import org.apache.spark.sql.catalyst.expressions.{And, Attribute, Cast, Expression, Literal} | ||
| import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, SubqueryAlias} | ||
| import org.apache.spark.sql.execution.datasources.LogicalRelation | ||
| import org.apache.spark.sql.internal.{SQLConf, StaticSQLConf} | ||
| import org.apache.spark.sql.types.{DataType, NullType, StringType, StructField, StructType} | ||
| import org.apache.spark.sql.types._ | ||
| import org.apache.spark.sql.{AnalysisException, Column, DataFrame, SparkSession} | ||
|
|
||
| import java.net.URI | ||
|
|
@@ -128,6 +128,7 @@ object HoodieSqlCommonUtils extends SparkAdapterSupport { | |
|
|
||
| /** | ||
| * Add the hoodie meta fields to the schema. | ||
| * | ||
| * @param schema | ||
| * @return | ||
| */ | ||
|
|
@@ -143,6 +144,7 @@ object HoodieSqlCommonUtils extends SparkAdapterSupport { | |
|
|
||
| /** | ||
| * Remove the meta fields from the schema. | ||
| * | ||
| * @param schema | ||
| * @return | ||
| */ | ||
|
|
@@ -171,6 +173,7 @@ object HoodieSqlCommonUtils extends SparkAdapterSupport { | |
|
|
||
| /** | ||
| * Get the table location. | ||
| * | ||
| * @param tableId | ||
| * @param spark | ||
| * @return | ||
|
|
@@ -233,6 +236,7 @@ object HoodieSqlCommonUtils extends SparkAdapterSupport { | |
|
|
||
| /** | ||
| * Split the expression to a sub expression seq by the AND operation. | ||
| * | ||
| * @param expression | ||
| * @return | ||
| */ | ||
|
|
@@ -262,15 +266,15 @@ object HoodieSqlCommonUtils extends SparkAdapterSupport { | |
| * Currently we support three kinds of instant time format for time travel query: | ||
| * 1、yyyy-MM-dd HH:mm:ss | ||
| * 2、yyyy-MM-dd | ||
| * This will convert to 'yyyyMMdd000000'. | ||
| * This will convert to 'yyyyMMdd000000'. | ||
| * 3、yyyyMMddHHmmss | ||
| */ | ||
| def formatQueryInstant(queryInstant: String): String = { | ||
| val instantLength = queryInstant.length | ||
| if (instantLength == 19 || instantLength == 23) { // for yyyy-MM-dd HH:mm:ss[.SSS] | ||
| HoodieInstantTimeGenerator.getInstantForDateString(queryInstant) | ||
| } else if (instantLength == HoodieInstantTimeGenerator.SECS_INSTANT_ID_LENGTH | ||
| || instantLength == HoodieInstantTimeGenerator.MILLIS_INSTANT_ID_LENGTH) { // for yyyyMMddHHmmss[SSS] | ||
| || instantLength == HoodieInstantTimeGenerator.MILLIS_INSTANT_ID_LENGTH) { // for yyyyMMddHHmmss[SSS] | ||
| HoodieActiveTimeline.parseDateFromInstantTime(queryInstant) // validate the format | ||
| queryInstant | ||
| } else if (instantLength == 10) { // for yyyy-MM-dd | ||
|
|
@@ -300,7 +304,7 @@ object HoodieSqlCommonUtils extends SparkAdapterSupport { | |
|
|
||
| // Find the origin column from schema by column name, throw an AnalysisException if the column | ||
| // reference is invalid. | ||
| def findColumnByName(schema: StructType, name: String, resolver: Resolver):Option[StructField] = { | ||
| def findColumnByName(schema: StructType, name: String, resolver: Resolver): Option[StructField] = { | ||
| schema.fields.collectFirst { | ||
| case field if resolver(field.name, name) => field | ||
| } | ||
|
|
@@ -372,4 +376,32 @@ object HoodieSqlCommonUtils extends SparkAdapterSupport { | |
| }.mkString(",") | ||
| partitionsToDrop | ||
| } | ||
|
|
||
| def getPartitionPathToTruncate(hoodieCatalogTable: HoodieCatalogTable, | ||
| table: CatalogTable, | ||
| partitionSpec: Option[TablePartitionSpec], | ||
| resolver: Resolver): String = { | ||
| val partCols = table.partitionColumnNames | ||
| val normalizedSpec: Seq[Map[String, String]] = Seq(partitionSpec.map { spec => | ||
| normalizePartitionSpec( | ||
| spec, | ||
| partCols, | ||
| table.identifier.quotedString, | ||
| resolver) | ||
| }.get) | ||
|
|
||
| val allPartitionPaths = hoodieCatalogTable.getPartitionPaths | ||
| val enableEncodeUrl = isUrlEncodeEnabled(allPartitionPaths, table) | ||
|
|
||
| val partitionsToTruncate = normalizedSpec.map { spec => | ||
| hoodieCatalogTable.partitionFields.map { partitionColumn => | ||
| if (enableEncodeUrl) { | ||
| partitionColumn + "=" + "\"" + spec(partitionColumn) + "\"" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this encode case did not call
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah. not sure if he is confusing w/ hive style partitioning. Don't we need to consider both? i.e. url encode and hive style partitioning ? snippet from KeyGenUtils
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The urlcode character appears in the partition, which cannot be deleted with single quotation marks. Double quotation marks are used after url decoding.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contains the processing of hive style partitioning, which is mainly to construct the where condition of delete sql.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see w/ latest commit, all changes in HoodieSqlCommonutils is reverted. So, where exactly we process url decoding ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. guess getPartitionPathToDrop() does that. |
||
| } else { | ||
| partitionColumn + "=" + "'" + spec(partitionColumn) + "'" | ||
| } | ||
| }.mkString(" and ") | ||
| }.mkString | ||
| partitionsToTruncate | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,7 +69,7 @@ class TestTruncateTable extends TestHoodieSqlBase { | |
|
|
||
| df.write.format("hudi") | ||
| .option(HoodieWriteConfig.TBL_NAME.key, tableName) | ||
| .option(TABLE_TYPE.key, MOR_TABLE_TYPE_OPT_VAL) | ||
| .option(TABLE_TYPE.key, COW_TABLE_TYPE_OPT_VAL) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why this test case change?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder how the tests are succeeding? bcoz, w/ latest master, delete partitions are lazy. only after cleaner gets a chance to clean up, the deleted partition may not show up when we make getAllPartitions(). Can you check the assertions in tests. Or are we asserting for records in the deleted partitions = 0 ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This case encountered this #5282 that was not covered by ut before. |
||
| .option(RECORDKEY_FIELD.key, "id") | ||
| .option(PRECOMBINE_FIELD.key, "ts") | ||
| .option(PARTITIONPATH_FIELD.key, "dt") | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.