{"record":{"id":"ba0fd5aa66ee9eaf","repo":"apache/iceberg","slug":"alter-table-has-no-changes-missing-both-distribut","errorCode":null,"errorMessage":"ALTER TABLE has no changes: missing both distribution and ordering clauses","messagePattern":"ALTER TABLE has no changes: missing both distribution and ordering clauses","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSqlExtensionsAstBuilder.scala","lineNumber":243,"sourceCode":"  override def visitDropIdentifierFields(ctx: DropIdentifierFieldsContext): DropIdentifierFields =\n    withOrigin(ctx) {\n      DropIdentifierFields(\n        typedVisit[Seq[String]](ctx.multipartIdentifier),\n        toSeq(ctx.fieldList.fields).map(_.getText))\n    }\n\n  /**\n   * Create a [[SetWriteDistributionAndOrdering]] for changing the write distribution and ordering.\n   */\n  override def visitSetWriteDistributionAndOrdering(\n      ctx: SetWriteDistributionAndOrderingContext): SetWriteDistributionAndOrdering = {\n\n    val tableName = typedVisit[Seq[String]](ctx.multipartIdentifier)\n\n    val (distributionSpec, orderingSpec) = toDistributionAndOrderingSpec(ctx.writeSpec)\n\n    if (distributionSpec == null && orderingSpec == null) {\n      throw new AnalysisException(\n        \"ALTER TABLE has no changes: missing both distribution and ordering clauses\")\n    }\n\n    val distributionMode = if (distributionSpec != null) {\n      Some(DistributionMode.HASH)\n    } else if (orderingSpec.UNORDERED != null) {\n      Some(DistributionMode.NONE)\n    } else if (orderingSpec.LOCALLY() != null) {\n      None\n    } else {\n      Some(DistributionMode.RANGE)\n    }\n\n    val ordering = if (orderingSpec != null && orderingSpec.order != null) {\n      toSeq(orderingSpec.order.fields).map(typedVisit[(Term, SortDirection, NullOrder)])\n    } else {\n      Seq.empty\n    }","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSqlExtensionsAstBuilder.scala#L225-L261","documentation":"The AST builder for ALTER TABLE ... WRITE (DISTRIBUTED|ORDERED BY ...) requires at least one of a distribution clause or an ordering clause. If the write spec is empty (no changes requested), an AnalysisException is thrown since the statement would be a no-op.","triggerScenarios":"Running 'ALTER TABLE t WRITE ...' where the write spec contains neither a distribution spec (DISTRIBUTED BY/HASH/etc.) nor an ordering spec (ORDERED BY/LOCALLY ORDERED BY/UNORDERED), e.g. 'ALTER TABLE t WRITE' with nothing after it that the grammar accepts.","commonSituations":"Incomplete SQL statements from generated scripts; users expecting the statement to reset distribution/ordering to defaults without specifying clauses.","solutions":["Add the intended clause, e.g. ALTER TABLE t WRITE ORDERED BY col; or ALTER TABLE t WRITE DISTRIBUTED BY PARTITION;","To reset to defaults, use ALTER TABLE t WRITE UNORDERED; or WRITE DISTRIBUTED BY PARTITION with no ordering","Drop the statement entirely if no change is intended"],"exampleFix":"// before\nALTER TABLE catalog.db.t WRITE;\n// after\nALTER TABLE catalog.db.t WRITE ORDERED BY id;","handlingStrategy":"validation","validationCode":"val spec = sqlText.stripPrefix(\"ALTER TABLE t WRITE \").trim\nrequire(spec.nonEmpty, \"ALTER TABLE WRITE requires DISTRIBUTED/ORDERED/UNORDERED/LOCALLY ORDERED clause\")","typeGuard":null,"tryCatchPattern":"try { spark.sql(ddl) } catch { case e: AnalysisException if e.getMessage.contains(\"no changes\") => log.warn(\"no-op write spec\") }","preventionTips":["Always include at least one distribution or ordering clause after WRITE","Use UNORDERED explicitly to reset ordering","Template-generate complete clauses rather than empty write specs"],"tags":["spark","sql","alter-table"],"backgroundTag":"missing-required-argument","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}