Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import java.io.Serializable;
import java.util.List;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.statement.select.PlainSelect;

public class PartitionDefinition implements Serializable {
Expand Down Expand Up @@ -39,7 +40,7 @@ public String toString() {
private boolean subPartition;
private boolean storageKeyword;
private boolean storageEngineUseEquals = true;
private String comment;
private StringValue commentValue;
private boolean commentUseEquals;
private String dataDirectory;
private boolean dataDirectoryUseEquals;
Expand Down Expand Up @@ -143,12 +144,26 @@ public void setStorageEngineUseEquals(boolean storageEngineUseEquals) {
this.storageEngineUseEquals = storageEngineUseEquals;
}

/** Returns the COMMENT literal's SQL text, for example {@code 'it''s'}, or null. */
public String getComment() {
return comment;
return commentValue != null ? commentValue.toString() : null;
}

/**
* Sets the COMMENT from a string literal's SQL text, read with standard escaping. Use
* {@link #setCommentValue(StringValue)} for another escaping. Null removes the comment.
*/
public void setComment(String comment) {
this.comment = comment;
commentValue = comment != null ? new StringValue(comment) : null;
}

/** Returns the COMMENT string literal; {@link StringValue#getNotExcapedValue()} decodes it. */
public StringValue getCommentValue() {
return commentValue;
}

public void setCommentValue(StringValue commentValue) {
this.commentValue = commentValue;
}

public boolean isCommentUseEquals() {
Expand Down Expand Up @@ -266,7 +281,7 @@ public String toString() {
}
appendOption(b, "ENGINE", storageEngine, storageEngineUseEquals);
}
appendOption(b, "COMMENT", comment, commentUseEquals);
appendOption(b, "COMMENT", getComment(), commentUseEquals);
appendOption(b, "DATA DIRECTORY", dataDirectory, dataDirectoryUseEquals);
appendOption(b, "INDEX DIRECTORY", indexDirectory, indexDirectoryUseEquals);
appendOption(b, "MAX_ROWS", maxRows, maxRowsUseEquals);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.schema.Table;

Expand All @@ -34,6 +35,7 @@ public class TableOption implements Serializable {
private List<IndexOption> storageParameters;
private ColumnOption.Storage tablespaceStorage;
private OnCommitAction onCommitAction;
private StringValue comment;

public enum Kind {
ENGINE, CHARACTER_SET, COLLATE, COMMENT, AUTO_INCREMENT, STATS_AUTO_RECALC, STATS_PERSISTENT, STATS_SAMPLE_PAGES, UNION, ENCRYPTION, PASSWORD, DATA_DIRECTORY, INDEX_DIRECTORY, SECONDARY_ENGINE, AUTOEXTEND_SIZE, INSERT_METHOD, PACK_KEYS, DELAY_KEY_WRITE, CHECKSUM, CONNECTION, COMPRESSION, STORAGE_PARAMETERS, WITHOUT_OIDS, ENGINE_ATTRIBUTE, SECONDARY_ENGINE_ATTRIBUTE, ROW_FORMAT, AVG_ROW_LENGTH, MAX_ROWS, MIN_ROWS, KEY_BLOCK_SIZE, TABLESPACE, FOREIGN_SERVER, ACCESS_METHOD, ON_COMMIT, OTHER
Expand Down Expand Up @@ -129,13 +131,49 @@ public void setStorageParameters(List<IndexOption> storageParameters) {
name = "WITH";
}

/**
* Returns the COMMENT string literal, or null for another kind, opaque tokens or a plain value
* set with {@link #setValue(String)}. {@link StringValue#getNotExcapedValue()} decodes it.
*/
public StringValue getComment() {
return comment;
}

/**
* Replaces the current contents with a COMMENT string literal and keeps the equals spelling; an
* existing COMMENT also keeps its name. A null literal omits the value.
*/
public void setComment(StringValue comment) {
String commentName = kind == Kind.COMMENT && name != null ? name : "COMMENT";
boolean equals = useEquals;
clearContents();
kind = Kind.COMMENT;
name = commentName;
useEquals = equals;
this.comment = comment;
}

public TableOption withComment(StringValue comment) {
setComment(comment);
return this;
}

public static TableOption comment(StringValue comment) {
TableOption option = new TableOption();
option.setComment(comment);
return option;
}

public void appendTo(StringBuilder builder,
java.util.function.Consumer<net.sf.jsqlparser.expression.Expression> expressionPrinter) {
if (foreignTableOptions != null) {
foreignTableOptions.appendTo(builder, expressionPrinter);
} else if (storageParameters != null) {
builder.append(name).append(useEquals ? " = " : " ");
IndexOption.appendListTo(builder, storageParameters, expressionPrinter);
} else if (comment != null) {
builder.append(name).append(useEquals ? " = " : " ");
expressionPrinter.accept(comment);
} else {
builder.append(toString());
}
Expand Down Expand Up @@ -183,6 +221,11 @@ public void setKind(Kind kind) {
if (kind != Kind.ON_COMMIT) {
onCommitAction = null;
}
if (kind != Kind.COMMENT && comment != null) {
// keep the literal's SQL text, as for other scalar values
value = comment.toString();
comment = null;
}
}

public String getName() {
Expand All @@ -204,16 +247,21 @@ public String getValue() {
if (onCommitAction != null) {
return onCommitAction.toString();
}
if (comment != null) {
return comment.toString();
}
return unionTables == null ? value : PlainSelect.getStringList(unionTables, true, true);
}

/** Sets a plain value; it replaces a COMMENT literal without being parsed. */
public void setValue(String value) {
tokens = null;
this.value = value;
foreignTableOptions = null;
unionTables = null;
storageParameters = null;
onCommitAction = null;
comment = null;
}

/** Returns the mutable MERGE table sources, including an empty UNION list. */
Expand Down Expand Up @@ -296,6 +344,7 @@ private void clearContents() {
unionTables = null;
storageParameters = null;
onCommitAction = null;
comment = null;
}

public TableOption withKind(Kind kind) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,12 @@ public static void visit(CreateTable table, Consumer<Expression> expressions,
visit(table.getPartitionBound(), expressions);
}

/** Shared CREATE/ALTER table option traversal. */
/** Shared CREATE/ALTER table option traversal, including COMMENT literals. */
public static void visit(net.sf.jsqlparser.statement.create.table.TableOption option,
Consumer<Expression> expressions, Consumer<Table> tables) {
if (option != null) {
visitOptions(option.getStorageParameters(), expressions);
accept(option.getComment(), expressions);
if (option.getUnionTables() != null) {
option.getUnionTables().forEach(source -> accept(source, tables));
}
Expand Down
11 changes: 9 additions & 2 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -16947,6 +16947,7 @@ TableOption MySqlTableOption(): {
TableOption.Kind kind = null;
TableOption option;
ColumnOption.Storage storage = null;
StringValue comment = null;
} {
(
tk=<K_UNION> { name = tk.image; kind = TableOption.Kind.UNION;
Expand Down Expand Up @@ -17017,10 +17018,16 @@ TableOption MySqlTableOption(): {
kind = TableOption.Kind.COMMENT;
}
[ "=" { useEquals = true; } ]
value=MySqlTableOptionValue()
// A string literal keeps its escaping; other values remain plain text
(
LOOKAHEAD({ getToken(1).kind == S_CHAR_LITERAL }) tk=<S_CHAR_LITERAL>
{ comment = stringValue(tk); }
| value=MySqlTableOptionValue()
)
)
{
option = new TableOption(kind, name, value, useEquals);
if (comment != null) { option.setComment(comment); }
if (unionTables != null) { option.setUnionTables(unionTables); }
option.setTablespaceStorage(storage);
return option;
Expand Down Expand Up @@ -19048,7 +19055,7 @@ void PartitionDefinitionOption(PartitionDefinition partitionDefinition):
|
<K_COMMENT> [ "=" { useEquals = true; } ] tk=<S_CHAR_LITERAL>
{
partitionDefinition.setComment(tk.image);
partitionDefinition.setCommentValue(stringValue(tk));
partitionDefinition.setCommentUseEquals(useEquals);
}
|
Expand Down
41 changes: 41 additions & 0 deletions src/site/sphinx/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,47 @@ Use ``TableOption.onCommit`` and ``TableOption.accessMethod`` to build them.
.setOnCommitAction(TableOption.OnCommitAction.PRESERVE_ROWS);
// CREATE TEMP TABLE t (id INT) USING heap ON COMMIT PRESERVE ROWS

MySQL table and partition comments
----------------------------------

A table ``COMMENT`` in CREATE TABLE, CREATE TABLE … AS SELECT and ALTER TABLE is a
``StringValue`` in ``TableOption.getComment()``. Partition and subpartition comments,
including those of ALTER TABLE ADD and REORGANIZE PARTITION, are in
``PartitionDefinition.getCommentValue()``. The literal records the escaping of the
parser configuration, so ``getNotExcapedValue()`` returns the text MySQL stores.

.. code-block:: java

CreateTable table = (CreateTable) CCJSqlParserUtil.parse(
"CREATE TABLE t (id INT) COMMENT = 'it\\'s' "
+ "PARTITION BY HASH (id) (PARTITION p0 COMMENT 'a\\\\b')",
parser -> parser.withDialect(Dialect.MYSQL));
TableOption option = table.getTableOption(TableOption.Kind.COMMENT).orElseThrow();
option.getComment().getNotExcapedValue(); // it's
option.getValue(); // 'it\'s'
table.getPartitioning().getPartitionDefinitions().get(0)
.getCommentValue().getNotExcapedValue(); // a\b

``getValue()``, ``getTokens()``, ``CreateTable.getTableOptionsStrings()``,
``AlterExpressionTableOption.getCommentText()`` and ``PartitionDefinition.getComment()``
still return the literal as written, and the SQL output is unchanged except that a
string prefix such as ``n'…'`` is printed in upper case, as in other string literals.
The table comment literal is rendered by the expression deparser and visited like a
column COMMENT literal.

``setComment``, ``withComment`` and the ``TableOption.comment`` factory replace the
option's contents with the literal and select COMMENT. They keep the equals spelling,
and an existing COMMENT also keeps its name; a null literal omits the value.
``setValue`` stores a plain value and ``setTokens`` opaque tokens. Neither is parsed,
so ``getComment()`` then returns null. Selecting another kind keeps the literal's SQL
text as a plain value. A COMMENT value that is not a string literal also stays a plain
value, for example a double-quoted string parsed without the MySQL dialect, where it
is a quoted identifier.

``PartitionDefinition.setComment(String)`` reads the SQL text of a literal with
standard escaping; pass a ``StringValue`` with another escaping to
``setCommentValue``.

Inspect PostgreSQL schema statements
------------------------------------

Expand Down
Loading
Loading