代码拉取完成,页面将自动刷新
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package sqlparser
import (
"strings"
)
// SQLNode defines the interface for all nodes
// generated by the parser.
type SQLNode interface {
Format(buf *TrackedBuffer)
}
// Statements.
type (
// Statement represents a statement.
Statement interface {
iStatement()
SQLNode
}
// SelectStatement any SELECT statement.
SelectStatement interface {
iSelectStatement()
iStatement()
iInsertRows()
AddOrder(*Order)
SetLimit(*Limit)
SQLNode
}
// Select represents a SELECT statement.
Select struct {
Cache string
Comments Comments
Distinct string
Hints string
SelectExprs SelectExprs
From TableExprs
Where *Where
GroupBy GroupBy
Having *Where
OrderBy OrderBy
Limit *Limit
Lock string
ForBackup string
}
// Union represents a UNION statement.
Union struct {
Type string
Left, Right SelectStatement
OrderBy OrderBy
Limit *Limit
Lock string
}
// ParenSelect is a parenthesized SELECT statement.
ParenSelect struct {
Select SelectStatement
}
// Insert represents an INSERT or REPLACE statement.
// Per the MySQL docs, http://dev.mysql.com/doc/refman/5.7/en/replace.html
// Replace is the counterpart to `INSERT IGNORE`, and works exactly like a
// normal INSERT except if the row exists. In that case it first deletes
// the row and re-inserts with new values. For that reason we keep it as an Insert struct.
// Replaces are currently disallowed in sharded schemas because
// of the implications the deletion part may have on vindexes.
Insert struct {
Action string
Comments Comments
Ignore string
Table TableName
Columns Columns
Rows InsertRows
OnDup OnDup
}
// Update represents an UPDATE statement.
Update struct {
Comments Comments
Table TableName
Exprs UpdateExprs
Where *Where
OrderBy OrderBy
Limit *Limit
}
// Delete represents a DELETE statement.
Delete struct {
Comments Comments
Table TableName
Where *Where
OrderBy OrderBy
Limit *Limit
}
// Set represents a SET statement.
Set struct {
Comments Comments
Exprs SetExprs
}
// DDL represents a CREATE, ALTER, DROP or RENAME statement.
// Table is set for AlterStr, DropStr, RenameStr.
// NewName is set for AlterStr, CreateStr, RenameStr.
DDL struct {
Action string
Engine string
Charset string
IndexName string
PartitionName string
BackendName string
IfExists bool
IfNotExists bool
Table TableName
NewName TableName
Database TableIdent
DatabaseOptions DatabaseOptionListOpt
TableSpec *TableSpec
// [UNIQUE | FULLTEXT | SPATIAL] index.
IndexType string
IndexOpts *IndexOptions
// Tables is set if Action is DropStr.
Tables TableNames
// table column operation
DropColumnName string
ModifyColumnDef *ColumnDefinition
// Partition options.
PartitionOptions PartitionOptions
PartitionNum *SQLVal
}
// Show represents a show statement.
Show struct {
Type string
Full string
Table TableName
Database TableName
From string
Limit *Limit
Filter *ShowFilter
}
// Checksum represents a CHECKSUM statement.
Checksum struct {
Table TableName
}
// Use represents a use statement.
Use struct {
DBName TableIdent
}
// OtherRead represents a DESCRIBE, or EXPLAIN statement.
// It should be used only as an indicator. It does not contain
// the full AST for the statement.
OtherRead struct{}
// OtherAdmin represents a misc statement that relies on ADMIN privileges,
// such as REPAIR, OPTIMIZE, or TRUNCATE statement.
// It should be used only as an indicator. It does not contain
// the full AST for the statement.
OtherAdmin struct{}
// Radon represents the radon statement.
Radon struct {
Action string
Row ValTuple
Table TableName
NewName TableName
}
// Explain represents a explain statement.
Explain struct{}
// Kill represents a KILL statement.
Kill struct {
QueryID *NumVal
}
// Transaction represents the transaction tuple.
Transaction struct {
Action string
}
// Xa represents a XA statement.
Xa struct{}
)
// ParenSelect can actually not be a top level statement,
// but we have to allow it because it's a requirement
// of SelectStatement.
func (*ParenSelect) iStatement() {}
func (*Union) iStatement() {}
func (*Select) iStatement() {}
func (*Insert) iStatement() {}
func (*Update) iStatement() {}
func (*Delete) iStatement() {}
func (*Set) iStatement() {}
func (*DDL) iStatement() {}
func (*Show) iStatement() {}
func (*Checksum) iStatement() {}
func (*Use) iStatement() {}
func (*OtherRead) iStatement() {}
func (*OtherAdmin) iStatement() {}
func (*Radon) iStatement() {}
func (*Explain) iStatement() {}
func (*Kill) iStatement() {}
func (*Transaction) iStatement() {}
func (*Xa) iStatement() {}
func (*Select) iSelectStatement() {}
func (*Union) iSelectStatement() {}
func (*ParenSelect) iSelectStatement() {}
type (
// InsertRows represents the rows for an INSERT statement.
InsertRows interface {
iInsertRows()
SQLNode
}
// Values represents a VALUES clause.
Values []ValTuple
)
func (*Select) iInsertRows() {}
func (*Union) iInsertRows() {}
func (Values) iInsertRows() {}
func (*ParenSelect) iInsertRows() {}
type DatabaseOptionListOpt struct {
DBOptList []*DatabaseOption
}
// TableOptions is used by TableSpec
type TableOptions struct {
Comment string
Engine string
Charset string
Type string
AvgRowLength string
Checksum string
Collate string
Compression string
Connection string
DataDirectory string
IndexDirectory string
DelayKeyWrite string
Encryption string
InsertMethod string
KeyBlockSize string
MaxRows string
MinRows string
PackKeys string
Password string
RowFormat string
StatsAutoRecalc string
StatsPersistent string
StatsSamplePages string
TableSpace string
}
// IndexOptions is used by IndexOpts.
type IndexOptions struct {
Columns []*IndexColumn
Using string
Comment string
BlockSize *SQLVal
Parser string
Algorithm string
Lock string
}
// IndexDefinition describes an index in a CREATE TABLE statement
type IndexDefinition struct {
Type string
Name ColIdent
Opts *IndexOptions
Primary bool
Unique bool
}
// TableSpec describes the structure of a table from a CREATE TABLE statement
type TableSpec struct {
Columns []*ColumnDefinition
Indexes []*IndexDefinition
Options TableOptions
}
// ColumnDefinition describes a column in a CREATE TABLE statement
type ColumnDefinition struct {
Name ColIdent
Type ColumnType
}
// ColumnType represents a sql type in a CREATE TABLE statement
// All optional fields are nil if not specified
type ColumnType struct {
// The base type string
Type string
// Generic field options.
NotNull BoolVal
Autoincrement BoolVal
Default *SQLVal
OnUpdate string
Comment *SQLVal
Collate *SQLVal
ColumnFormat string
Storage string
// Numeric field options
Length *SQLVal
Unsigned BoolVal
Zerofill BoolVal
Scale *SQLVal
// Text field options
Charset string
// Enum values
EnumValues []string
// Key specification
PrimaryKeyOpt ColumnPrimaryKeyOption
UniqueKeyOpt ColumnUniqueKeyOption
}
// ShowFilter is show tables filter
type ShowFilter struct {
Like string
Filter Expr
}
// Comments represents a list of comments.
type Comments [][]byte
// SelectExprs represents SELECT expressions.
type SelectExprs []SelectExpr
type (
// SelectExpr represents a SELECT expression.
SelectExpr interface {
iSelectExpr()
SQLNode
// clone used to deep copy a new SelectExpr.
clone() SelectExpr
}
// StarExpr defines a '*' or 'table.*' expression.
StarExpr struct {
TableName TableName
}
// AliasedExpr defines an aliased SELECT expression.
AliasedExpr struct {
Expr Expr
As ColIdent
}
// Nextval defines the NEXT VALUE expression.
Nextval struct {
Expr Expr
}
)
func (*StarExpr) iSelectExpr() {}
func (*AliasedExpr) iSelectExpr() {}
func (Nextval) iSelectExpr() {}
// Columns represents an insert column list.
type Columns []ColIdent
// TableExprs represents a list of table expressions.
type TableExprs []TableExpr
type (
// TableExpr represents a table expression.
TableExpr interface {
iTableExpr()
SQLNode
}
// AliasedTableExpr represents a table expression
// coupled with an optional alias or index hint.
// If As is empty, no alias was used.
AliasedTableExpr struct {
Expr SimpleTableExpr
As TableIdent
Hints *IndexHints
}
// ParenTableExpr represents a parenthesized list of TableExpr.
ParenTableExpr struct {
Exprs TableExprs
}
// JoinTableExpr represents a TableExpr that's a JOIN operation.
JoinTableExpr struct {
LeftExpr TableExpr
Join string
RightExpr TableExpr
On Expr
}
)
func (*AliasedTableExpr) iTableExpr() {}
func (*ParenTableExpr) iTableExpr() {}
func (*JoinTableExpr) iTableExpr() {}
type (
// SimpleTableExpr represents a simple table expression.
SimpleTableExpr interface {
iSimpleTableExpr()
SQLNode
}
// TableName represents a table name.
// Qualifier, if specified, represents a database or keyspace.
// TableName is a value struct whose fields are case sensitive.
// This means two TableName vars can be compared for equality
// and a TableName can also be used as key in a map.
TableName struct {
Name, Qualifier TableIdent
}
// Subquery represents a subquery.
Subquery struct {
Select SelectStatement
}
)
func (TableName) iSimpleTableExpr() {}
func (*Subquery) iSimpleTableExpr() {}
// TableNames is a list of TableName.
type TableNames []TableName
// IndexHints represents a list of index hints.
type IndexHints struct {
Type string
Indexes []ColIdent
}
// Where represents a WHERE or HAVING clause.
type Where struct {
Type string
Expr Expr
}
// Exprs represents a list of value expressions.
// It's not a valid expression because it's not parenthesized.
type Exprs []Expr
// Expressions.
type (
// Expr represents an expression.
Expr interface {
iExpr()
SQLNode
// clone used to deep copy a new Expr.
clone() Expr
}
// AndExpr represents an AND expression.
AndExpr struct {
Left, Right Expr
}
// OrExpr represents an OR expression.
OrExpr struct {
Left, Right Expr
}
// NotExpr represents a NOT expression.
NotExpr struct {
Expr Expr
}
// ParenExpr represents a parenthesized boolean expression.
ParenExpr struct {
Expr Expr
}
// ComparisonExpr represents a two-value comparison expression.
ComparisonExpr struct {
Operator string
Left, Right Expr
Escape Expr
}
// RangeCond represents a BETWEEN or a NOT BETWEEN expression.
RangeCond struct {
Operator string
Left Expr
From, To Expr
}
// IsExpr represents an IS ... or an IS NOT ... expression.
IsExpr struct {
Operator string
Expr Expr
}
// ExistsExpr represents an EXISTS expression.
ExistsExpr struct {
Subquery *Subquery
}
// SQLVal represents a single value.
SQLVal struct {
Type ValType
Val []byte
}
// NullVal represents a NULL value.
NullVal struct{}
// BoolVal is true or false.
BoolVal bool
// ColName represents a column name.
ColName struct {
// Metadata is not populated by the parser.
// It's a placeholder for analyzers to store
// additional data, typically info about which
// table or column this node references.
Metadata interface{}
Name ColIdent
Qualifier TableName
}
// ColTuple represents a list of column values.
// It can be ValTuple, Subquery, ListArg.
ColTuple interface {
iColTuple()
Expr
}
// ValTuple represents a tuple of actual values.
ValTuple Exprs
// ListArg represents a named list argument.
ListArg []byte
// BinaryExpr represents a binary value expression.
BinaryExpr struct {
Operator string
Left, Right Expr
}
// UnaryExpr represents a unary value expression.
UnaryExpr struct {
Operator string
Expr Expr
}
// IntervalExpr represents a date-time INTERVAL expression.
IntervalExpr struct {
Expr Expr
Unit string
}
// CollateExpr represents dynamic collate operator.
CollateExpr struct {
Expr Expr
Charset string
}
// FuncExpr represents a function call.
FuncExpr struct {
Qualifier TableIdent
Name ColIdent
Distinct bool
Exprs SelectExprs
}
// GroupConcatExpr represents a call to GROUP_CONCAT
GroupConcatExpr struct {
Distinct string
Exprs SelectExprs
OrderBy OrderBy
Separator string
}
// ValuesFuncExpr represents a function call.
ValuesFuncExpr struct {
Name ColIdent
Resolved Expr
}
// ConvertExpr represents a call to CONVERT(expr, type)
// or it's equivalent CAST(expr AS type). Both are rewritten to the former.
ConvertExpr struct {
Expr Expr
Type *ConvertType
}
// ConvertUsingExpr represents a call to CONVERT(expr USING charset).
ConvertUsingExpr struct {
Expr Expr
Type string
}
// MatchExpr represents a call to the MATCH function
MatchExpr struct {
Columns SelectExprs
Expr Expr
Option string
}
// CaseExpr represents a CASE expression.
CaseExpr struct {
Expr Expr
Whens []*When
Else Expr
}
// Default represents a DEFAULT expression.
Default struct {
ColName string
}
)
func (*AndExpr) iExpr() {}
func (*OrExpr) iExpr() {}
func (*NotExpr) iExpr() {}
func (*ParenExpr) iExpr() {}
func (*ComparisonExpr) iExpr() {}
func (*RangeCond) iExpr() {}
func (*IsExpr) iExpr() {}
func (*ExistsExpr) iExpr() {}
func (*SQLVal) iExpr() {}
func (*NullVal) iExpr() {}
func (BoolVal) iExpr() {}
func (*ColName) iExpr() {}
func (ValTuple) iExpr() {}
func (*Subquery) iExpr() {}
func (ListArg) iExpr() {}
func (*BinaryExpr) iExpr() {}
func (*UnaryExpr) iExpr() {}
func (*IntervalExpr) iExpr() {}
func (*CollateExpr) iExpr() {}
func (*FuncExpr) iExpr() {}
func (*GroupConcatExpr) iExpr() {}
func (*CaseExpr) iExpr() {}
func (*ValuesFuncExpr) iExpr() {}
func (*ConvertExpr) iExpr() {}
func (*ConvertUsingExpr) iExpr() {}
func (*MatchExpr) iExpr() {}
func (*Default) iExpr() {}
func (ValTuple) iColTuple() {}
func (*Subquery) iColTuple() {}
func (ListArg) iColTuple() {}
// ConvertType represents the type in call to CONVERT(expr, type)
type ConvertType struct {
Type string
Length *SQLVal
Scale *SQLVal
Operator string
Charset string
}
// When represents a WHEN sub-expression.
type When struct {
Cond Expr
Val Expr
}
// GroupBy represents a GROUP BY clause.
type GroupBy Exprs
// OrderBy represents an ORDER By clause.
type OrderBy []*Order
// Order represents an ordering expression.
type Order struct {
Expr Expr
Direction string
}
// Limit represents a LIMIT clause.
type Limit struct {
Offset, Rowcount Expr
}
// UpdateExprs represents a list of update expressions.
type UpdateExprs []*UpdateExpr
// UpdateExpr represents an update expression.
type UpdateExpr struct {
Name *ColName
Expr Expr
}
// OnDup represents an ON DUPLICATE KEY clause.
type OnDup UpdateExprs
// SetExprs represents a list of set expressions.
type SetExprs []*SetExpr
// SetExpr represents a set expression.
type SetExpr struct {
// global|session
Scope string
Type ColIdent
Val SetVal
}
type (
// SetVal represents a set variable value.
SetVal interface {
SQLNode
iSetVal()
}
// OptVal represents the set variable value.
// See https://dev.mysql.com/doc/refman/5.7/en/set-variable.html
OptVal struct {
Value Expr
}
// TxnVal represents the set-transaction characteristic.
// See https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
TxnVal struct {
Level string
Mode string
}
)
func (*OptVal) iSetVal() {}
func (*TxnVal) iSetVal() {}
// ColIdent is a case insensitive SQL identifier. It will be escaped with
// backquotes if necessary.
type ColIdent struct {
// This artifact prevents this struct from being compared
// with itself. It consumes no space as long as it's not the
// last field in the struct.
_ [0]struct{ _ []byte }
val, lowered string
}
// TableIdent is a case sensitive SQL identifier. It will be escaped with
// backquotes if necessary.
type TableIdent struct {
v string
}
// Format formats the node.
func (node *Select) Format(buf *TrackedBuffer) {
buf.Myprintf("select %v%s%s%s%v from %v%v%v%v%v%v%s",
node.Comments, node.Cache, node.Distinct, node.Hints, node.SelectExprs,
node.From, node.Where,
node.GroupBy, node.Having, node.OrderBy,
node.Limit, node.Lock)
}
// AddOrder adds an order by element
func (node *Select) AddOrder(order *Order) {
node.OrderBy = append(node.OrderBy, order)
}
// SetLimit sets the limit clause
func (node *Select) SetLimit(limit *Limit) {
node.Limit = limit
}
// Format formats the node.
func (node *ParenSelect) Format(buf *TrackedBuffer) {
buf.Myprintf("(%v)", node.Select)
}
// AddOrder adds an order by element
func (node *ParenSelect) AddOrder(order *Order) {
panic("unreachable")
}
// SetLimit sets the limit clause
func (node *ParenSelect) SetLimit(limit *Limit) {
panic("unreachable")
}
// Format formats the node.
func (node *Union) Format(buf *TrackedBuffer) {
buf.Myprintf("%v %s %v%v%v%s", node.Left, node.Type, node.Right,
node.OrderBy, node.Limit, node.Lock)
}
// AddOrder adds an order by element
func (node *Union) AddOrder(order *Order) {
node.OrderBy = append(node.OrderBy, order)
}
// SetLimit sets the limit clause
func (node *Union) SetLimit(limit *Limit) {
node.Limit = limit
}
// Format formats the node.
func (node *Insert) Format(buf *TrackedBuffer) {
buf.Myprintf("%s %v%sinto %v%v %v%v",
node.Action,
node.Comments, node.Ignore,
node.Table, node.Columns, node.Rows, node.OnDup)
}
// Format formats the node.
func (node *Update) Format(buf *TrackedBuffer) {
buf.Myprintf("update %v%v set %v%v%v%v",
node.Comments, node.Table,
node.Exprs, node.Where, node.OrderBy, node.Limit)
}
// Format formats the node.
func (node *Delete) Format(buf *TrackedBuffer) {
buf.Myprintf("delete %vfrom %v%v%v%v", node.Comments, node.Table, node.Where, node.OrderBy, node.Limit)
}
// Format formats the node.
func (node *Set) Format(buf *TrackedBuffer) {
buf.Myprintf("set %v%v", node.Comments, node.Exprs)
}
// Format formats the node.
func (node *Checksum) Format(buf *TrackedBuffer) {
buf.Myprintf("checksum table %v", node.Table)
}
// Format formats the node.
func (node *DDL) Format(buf *TrackedBuffer) {
switch node.Action {
case CreateDBStr:
ifnotexists := ""
if node.IfNotExists {
ifnotexists = " if not exists"
}
buf.Myprintf("%s%s %s", node.Action, ifnotexists, node.Database.String())
node.DatabaseOptions.Format(buf)
case DropDBStr:
exists := ""
if node.IfExists {
exists = " if exists"
}
buf.Myprintf("%s%s %s", node.Action, exists, node.Database.String())
case CreateTableStr:
ifnotexists := ""
if node.IfNotExists {
ifnotexists = " if not exists"
}
if node.TableSpec == nil {
buf.Myprintf("%s%s %v", node.Action, ifnotexists, node.NewName)
} else {
buf.Myprintf("%s%s %v %v", node.Action, ifnotexists, node.NewName, node.TableSpec)
}
case CreateIndexStr:
buf.Myprintf("create %s%s on %v%v", node.IndexType, node.IndexName, node.NewName, node.IndexOpts)
case DropTableStr:
exists := ""
if node.IfExists {
exists = " if exists"
}
buf.Myprintf("%s%s %v", node.Action, exists, node.Tables)
case DropIndexStr:
buf.Myprintf("%s %s on %v", node.Action, node.IndexName, node.Table)
case RenameStr:
buf.Myprintf("%s %v to %v", node.Action, node.Table, node.NewName)
case AlterStr:
buf.Myprintf("%s table %v", node.Action, node.NewName)
case AlterEngineStr:
buf.Myprintf("%s %v engine = %s", node.Action, node.NewName, node.Engine)
case AlterCharsetStr:
buf.Myprintf("alter table %v convert to character set %s", node.NewName, node.Charset)
case AlterAddColumnStr:
buf.Myprintf("alter table %v add column %v", node.NewName, node.TableSpec)
case AlterDropColumnStr:
buf.Myprintf("alter table %v drop column `%s`", node.NewName, node.DropColumnName)
case AlterModifyColumnStr:
buf.Myprintf("alter table %v modify column %v", node.NewName, node.ModifyColumnDef)
case TruncateTableStr:
buf.Myprintf("%s %v", node.Action, node.NewName)
}
}
// Format formats the node
func (optList DatabaseOptionListOpt) Format(buf *TrackedBuffer) {
for _, dbOpt := range optList.DBOptList {
buf.Myprintf(" %s %s", dbOpt.CharsetOrCollate, dbOpt.Value)
}
}
// Format formats the node.
func (opts TableOptions) Format(buf *TrackedBuffer) {
if opts.Comment != "" {
buf.Myprintf(" comment=%s", opts.Comment)
}
if opts.Engine != "" {
buf.Myprintf(" engine=%s", opts.Engine)
}
if opts.Charset != "" {
buf.Myprintf(" default charset=%s", opts.Charset)
}
if opts.AvgRowLength != "" {
buf.Myprintf(" avg_row_length=%s", opts.AvgRowLength)
}
if opts.Checksum != "" {
buf.Myprintf(" checksum=%s", opts.Checksum)
}
if opts.Collate != "" {
buf.Myprintf(" collate=%s", opts.Collate)
}
if opts.Compression != "" {
buf.Myprintf(" compression=%s", opts.Compression)
}
if opts.Connection != "" {
buf.Myprintf(" connection=%s", opts.Connection)
}
if opts.DataDirectory != "" {
buf.Myprintf(" data directory=%s", opts.DataDirectory)
}
if opts.IndexDirectory != "" {
buf.Myprintf(" index directory=%s", opts.IndexDirectory)
}
if opts.DelayKeyWrite != "" {
buf.Myprintf(" delay_key_write=%s", opts.DelayKeyWrite)
}
if opts.Encryption != "" {
buf.Myprintf(" encryption=%s", opts.Encryption)
}
if opts.InsertMethod != "" {
buf.Myprintf(" insert_method=%s", opts.InsertMethod)
}
if opts.InsertMethod != "" {
buf.Myprintf(" key_block_size=%s", opts.KeyBlockSize)
}
if opts.MaxRows != "" {
buf.Myprintf(" max_rows=%s", opts.MaxRows)
}
if opts.MinRows != "" {
buf.Myprintf(" min_rows=%s", opts.MinRows)
}
if opts.PackKeys != "" {
buf.Myprintf(" pack_keys=%s", opts.PackKeys)
}
if opts.Password != "" {
buf.Myprintf(" password=%s", opts.Password)
}
if opts.RowFormat != "" {
buf.Myprintf(" row_format=%s", opts.RowFormat)
}
if opts.StatsAutoRecalc != "" {
buf.Myprintf(" stats_auto_recalc=%s", opts.StatsAutoRecalc)
}
if opts.StatsPersistent != "" {
buf.Myprintf(" stats_persistent=%s", opts.StatsPersistent)
}
if opts.StatsSamplePages != "" {
buf.Myprintf(" stats_sample_pages=%s", opts.StatsSamplePages)
}
if opts.TableSpace != "" {
buf.Myprintf(" tablespace=%s", opts.TableSpace)
}
}
// Format formats the node.
func (opts *IndexOptions) Format(buf *TrackedBuffer) {
buf.Myprintf("(")
for i, col := range opts.Columns {
if i != 0 {
buf.Myprintf(", `%s`", col.Column.String())
} else {
buf.Myprintf("`%s`", col.Column.String())
}
if col.Length != nil {
buf.Myprintf("(%v)", col.Length)
}
}
buf.Myprintf(")")
if opts.Using != "" {
buf.Myprintf(" using %s", opts.Using)
}
if opts.Comment != "" {
buf.Myprintf(" comment %s", opts.Comment)
}
if opts.BlockSize != nil {
buf.Myprintf(" key_block_size = %v", opts.BlockSize)
}
if opts.Parser != "" {
buf.Myprintf(" WITH PARSER %s", opts.Parser)
}
if opts.Algorithm != "" {
buf.Myprintf(" algorithm = %s", opts.Algorithm)
}
if opts.Lock != "" {
buf.Myprintf(" lock = %s", opts.Lock)
}
}
// Format formats the node.
func (ts *TableSpec) Format(buf *TrackedBuffer) {
buf.Myprintf("(\n")
for i, col := range ts.Columns {
if i == 0 {
buf.Myprintf("\t%v", col)
} else {
buf.Myprintf(",\n\t%v", col)
}
}
for _, idx := range ts.Indexes {
buf.Myprintf(",\n\t%v", idx)
}
buf.Myprintf("\n)%v", ts.Options)
}
// Format formats the node.
func (col *ColumnDefinition) Format(buf *TrackedBuffer) {
buf.Myprintf("`%s` %v", col.Name.String(), &col.Type)
}
// Format returns a canonical string representation of the type and all relevant options
func (ct *ColumnType) Format(buf *TrackedBuffer) {
buf.Myprintf("%s", ct.Type)
if ct.Length != nil && ct.Scale != nil {
buf.Myprintf("(%v,%v)", ct.Length, ct.Scale)
} else if ct.Length != nil {
buf.Myprintf("(%v)", ct.Length)
}
if ct.EnumValues != nil {
buf.Myprintf("(%s)", strings.Join(ct.EnumValues, ", "))
}
opts := make([]string, 0, 16)
if ct.Unsigned {
opts = append(opts, keywordStrings[UNSIGNED])
}
if ct.Zerofill {
opts = append(opts, keywordStrings[ZEROFILL])
}
if ct.Charset != "" {
opts = append(opts, keywordStrings[CHARACTER], keywordStrings[SET], ct.Charset)
}
if ct.Collate != nil {
opts = append(opts, keywordStrings[COLLATE], String(ct.Collate))
}
if ct.ColumnFormat != "" {
opts = append(opts, keywordStrings[COLUMN_FORMAT], ct.ColumnFormat)
}
if ct.Storage != "" {
opts = append(opts, keywordStrings[STORAGE], ct.Storage)
}
if ct.NotNull {
opts = append(opts, keywordStrings[NOT], keywordStrings[NULL])
}
if ct.Default != nil {
opts = append(opts, keywordStrings[DEFAULT], String(ct.Default))
}
if ct.OnUpdate != "" {
opts = append(opts, keywordStrings[ON], keywordStrings[UPDATE], ct.OnUpdate)
}
if ct.Autoincrement {
opts = append(opts, keywordStrings[AUTO_INCREMENT])
}
if ct.Comment != nil {
opts = append(opts, keywordStrings[COMMENT_KEYWORD], String(ct.Comment))
}
if ct.PrimaryKeyOpt == ColKeyPrimary {
opts = append(opts, keywordStrings[PRIMARY], keywordStrings[KEY])
}
if ct.UniqueKeyOpt == ColKeyUniqueKey {
opts = append(opts, keywordStrings[UNIQUE], keywordStrings[KEY])
}
if len(opts) != 0 {
buf.Myprintf(" %s", strings.Join(opts, " "))
}
}
// Format formats the node.
func (idx *IndexDefinition) Format(buf *TrackedBuffer) {
if idx.Primary {
buf.Myprintf("%s", idx.Type)
} else {
buf.Myprintf("%s `%v`", idx.Type, idx.Name)
}
buf.Myprintf(" %v", idx.Opts)
}
// Format formats the node.
func (node *Show) Format(buf *TrackedBuffer) {
switch node.Type {
case ShowCreateDatabaseStr:
buf.Myprintf("show %s %v", node.Type, node.Database)
case ShowTableStatusStr:
buf.Myprintf("show %s", node.Type)
if node.Database.Name.String() != "" {
buf.Myprintf(" from %s", node.Database.Name.String())
}
case ShowCreateTableStr:
buf.Myprintf("show %s %v", node.Type, node.Table)
case ShowTablesStr:
buf.Myprintf("show %s%s", node.Full, node.Type)
if node.Database.Name.String() != "" {
buf.Myprintf(" from %s", node.Database.Name.String())
}
if node.Filter != nil {
buf.Myprintf("%v", node.Filter)
}
case ShowBinlogEventsStr:
buf.Myprintf("show %s", node.Type)
if node.From != "" {
buf.Myprintf(" from gtid '%s'", node.From)
}
buf.Myprintf("%v", node.Limit)
case ShowColumnsStr:
buf.Myprintf("show %s%s", node.Full, node.Type)
if node.Table.Name.String() != "" {
buf.Myprintf(" from %v", node.Table)
}
if node.Filter != nil {
buf.Myprintf("%v", node.Filter)
}
default:
buf.Myprintf("show %s", node.Type)
}
}
// Format formats the node.
func (node *ShowFilter) Format(buf *TrackedBuffer) {
if node == nil {
return
}
if node.Like != "" {
buf.Myprintf(" like '%s'", node.Like)
} else {
buf.Myprintf(" where %v", node.Filter)
}
}
// Format formats the node.
func (node *Use) Format(buf *TrackedBuffer) {
buf.Myprintf("use %v", node.DBName)
}
// Format formats the node.
func (node *OtherRead) Format(buf *TrackedBuffer) {
buf.WriteString("otherread")
}
// Format formats the node.
func (node *OtherAdmin) Format(buf *TrackedBuffer) {
buf.WriteString("otheradmin")
}
// Format formats the node.
func (node Comments) Format(buf *TrackedBuffer) {
for _, c := range node {
buf.Myprintf("%s ", c)
}
}
// Format formats the node.
func (node SelectExprs) Format(buf *TrackedBuffer) {
var prefix string
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node *StarExpr) Format(buf *TrackedBuffer) {
if !node.TableName.IsEmpty() {
buf.Myprintf("%v.", node.TableName)
}
buf.Myprintf("*")
}
func (node *StarExpr) clone() SelectExpr {
return &StarExpr{
TableName: node.TableName,
}
}
// Format formats the node.
func (node *AliasedExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v", node.Expr)
if !node.As.IsEmpty() {
buf.Myprintf(" as %v", node.As)
}
}
func (node *AliasedExpr) clone() SelectExpr {
return &AliasedExpr{
Expr: CloneExpr(node.Expr),
As: node.As,
}
}
// Format formats the node.
func (node Nextval) Format(buf *TrackedBuffer) {
buf.Myprintf("next %v values", node.Expr)
}
func (node Nextval) clone() SelectExpr {
return Nextval{
Expr: CloneExpr(node.Expr),
}
}
// Format formats the node.
func (node Columns) Format(buf *TrackedBuffer) {
if node == nil {
return
}
prefix := "("
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
buf.WriteString(")")
}
// Format formats the node.
func (node TableExprs) Format(buf *TrackedBuffer) {
var prefix string
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node *AliasedTableExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v", node.Expr)
if !node.As.IsEmpty() {
buf.Myprintf(" as %v", node.As)
}
if node.Hints != nil {
// Hint node provides the space padding.
buf.Myprintf("%v", node.Hints)
}
}
// Format formats the node.
func (node TableNames) Format(buf *TrackedBuffer) {
var prefix string
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node TableName) Format(buf *TrackedBuffer) {
if node.IsEmpty() {
return
}
if !node.Qualifier.IsEmpty() {
buf.Myprintf("%v.", node.Qualifier)
}
buf.Myprintf("%v", node.Name)
}
// Format formats the node.
func (node *ParenTableExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("(%v)", node.Exprs)
}
// Format formats the node.
func (node *JoinTableExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v %s %v", node.LeftExpr, node.Join, node.RightExpr)
if node.On != nil {
buf.Myprintf(" on %v", node.On)
}
}
// Format formats the node.
func (node *IndexHints) Format(buf *TrackedBuffer) {
buf.Myprintf(" %sindex ", node.Type)
prefix := "("
for _, n := range node.Indexes {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
buf.Myprintf(")")
}
// Format formats the node.
func (node *Where) Format(buf *TrackedBuffer) {
if node == nil || node.Expr == nil {
return
}
buf.Myprintf(" %s %v", node.Type, node.Expr)
}
// Format formats the node.
func (node Exprs) Format(buf *TrackedBuffer) {
var prefix string
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node *AndExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v and %v", node.Left, node.Right)
}
func (node *AndExpr) clone() Expr {
return &AndExpr{
Left: CloneExpr(node.Left),
Right: CloneExpr(node.Right),
}
}
// Format formats the node.
func (node *OrExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v or %v", node.Left, node.Right)
}
func (node *OrExpr) clone() Expr {
return &OrExpr{
Left: CloneExpr(node.Left),
Right: CloneExpr(node.Right),
}
}
// Format formats the node.
func (node *NotExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("not %v", node.Expr)
}
func (node *NotExpr) clone() Expr {
return &NotExpr{
Expr: CloneExpr(node.Expr),
}
}
// Format formats the node.
func (node *ParenExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("(%v)", node.Expr)
}
func (node *ParenExpr) clone() Expr {
return &ParenExpr{
Expr: CloneExpr(node.Expr),
}
}
// Format formats the node.
func (node *ComparisonExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v %s %v", node.Left, node.Operator, node.Right)
if node.Escape != nil {
buf.Myprintf(" escape %v", node.Escape)
}
}
func (node *ComparisonExpr) clone() Expr {
return &ComparisonExpr{
Operator: node.Operator,
Left: CloneExpr(node.Left),
Right: CloneExpr(node.Right),
Escape: CloneExpr(node.Escape),
}
}
// Format formats the node.
func (node *RangeCond) Format(buf *TrackedBuffer) {
buf.Myprintf("%v %s %v and %v", node.Left, node.Operator, node.From, node.To)
}
func (node *RangeCond) clone() Expr {
return &RangeCond{
Operator: node.Operator,
Left: CloneExpr(node.Left),
From: CloneExpr(node.From),
To: CloneExpr(node.To),
}
}
// Format formats the node.
func (node *IsExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v %s", node.Expr, node.Operator)
}
func (node *IsExpr) clone() Expr {
return &IsExpr{
Operator: node.Operator,
Expr: CloneExpr(node.Expr),
}
}
// Format formats the node.
func (node *ExistsExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("exists %v", node.Subquery)
}
func (node *ExistsExpr) clone() Expr {
return nil
}
// Format formats the node.
func (node *SQLVal) Format(buf *TrackedBuffer) {
switch node.Type {
case StrVal:
sqltypes.MakeTrusted(sqltypes.VarBinary, node.Val).EncodeSQL(buf)
case IntVal, FloatVal, HexNum, StrValWithoutQuote:
buf.Myprintf("%s", []byte(node.Val))
case HexVal:
buf.Myprintf("X'%s'", []byte(node.Val))
case ValArg:
buf.WriteArg(string(node.Val))
default:
panic("unexpected")
}
}
func (node *SQLVal) clone() Expr {
return &SQLVal{
Type: node.Type,
Val: node.Val,
}
}
// Format formats the node.
func (node *NullVal) Format(buf *TrackedBuffer) {
buf.Myprintf("null")
}
func (node *NullVal) clone() Expr {
return &NullVal{}
}
// Format formats the node.
func (node BoolVal) Format(buf *TrackedBuffer) {
if node {
buf.Myprintf("true")
} else {
buf.Myprintf("false")
}
}
func (node BoolVal) clone() Expr {
return node
}
// Format formats the node.
func (node *ColName) Format(buf *TrackedBuffer) {
if !node.Qualifier.IsEmpty() {
buf.Myprintf("%v.", node.Qualifier)
}
buf.Myprintf("%v", node.Name)
}
func (node *ColName) clone() Expr {
return &ColName{
Name: node.Name,
Qualifier: node.Qualifier,
}
}
// Format formats the node.
func (node ValTuple) Format(buf *TrackedBuffer) {
buf.Myprintf("(%v)", Exprs(node))
}
func (node ValTuple) clone() Expr {
var tuple ValTuple
for _, e := range node {
exp := CloneExpr(e)
tuple = append(tuple, exp)
}
return tuple
}
// Format formats the node.
func (node *Subquery) Format(buf *TrackedBuffer) {
buf.Myprintf("(%v)", node.Select)
}
func (node *Subquery) clone() Expr {
return nil
}
// Format formats the node.
func (node ListArg) Format(buf *TrackedBuffer) {
buf.WriteArg(string(node))
}
func (node ListArg) clone() Expr {
return node
}
// Format formats the node.
func (node *BinaryExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v %s %v", node.Left, node.Operator, node.Right)
}
func (node *BinaryExpr) clone() Expr {
return &BinaryExpr{
Operator: node.Operator,
Left: CloneExpr(node.Left),
Right: CloneExpr(node.Right),
}
}
// Format formats the node.
func (node *UnaryExpr) Format(buf *TrackedBuffer) {
if _, unary := node.Expr.(*UnaryExpr); unary {
buf.Myprintf("%s %v", node.Operator, node.Expr)
return
}
buf.Myprintf("%s%v", node.Operator, node.Expr)
}
func (node *UnaryExpr) clone() Expr {
return &UnaryExpr{
Operator: node.Operator,
Expr: CloneExpr(node.Expr),
}
}
// Format formats the node.
func (node *IntervalExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("interval %v %s", node.Expr, node.Unit)
}
func (node *IntervalExpr) clone() Expr {
return &IntervalExpr{
Expr: CloneExpr(node.Expr),
Unit: node.Unit,
}
}
// Format formats the node.
func (node *CollateExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v", node.Expr)
if node.Charset != "" {
buf.Myprintf(" collate %s", node.Charset)
}
}
func (node *CollateExpr) clone() Expr {
return &CollateExpr{
Expr: CloneExpr(node.Expr),
Charset: node.Charset,
}
}
// Format formats the node.
func (node *FuncExpr) Format(buf *TrackedBuffer) {
var distinct string
if node.Distinct {
distinct = "distinct "
}
if !node.Qualifier.IsEmpty() {
buf.Myprintf("%v.", node.Qualifier)
}
// Function names should not be back-quoted even
// if they match a reserved word. So, print the
// name as is.
buf.Myprintf("%s(%s%v)", node.Name.String(), distinct, node.Exprs)
}
func (node *FuncExpr) clone() Expr {
var exprs SelectExprs
for _, e := range node.Exprs {
exp := CloneSelectExpr(e)
exprs = append(exprs, exp)
}
return &FuncExpr{
Qualifier: node.Qualifier,
Name: node.Name,
Distinct: node.Distinct,
Exprs: exprs,
}
}
// Format formats the node
func (node *GroupConcatExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("group_concat(%s%v%v%s)", node.Distinct, node.Exprs, node.OrderBy, node.Separator)
}
func (node *GroupConcatExpr) clone() Expr {
var exprs SelectExprs
for _, e := range node.Exprs {
exp := CloneSelectExpr(e)
exprs = append(exprs, exp)
}
var orders OrderBy
for _, order := range node.OrderBy {
o := &Order{
Expr: CloneExpr(order.Expr),
Direction: order.Direction,
}
orders = append(orders, o)
}
return &GroupConcatExpr{
Distinct: node.Distinct,
Exprs: exprs,
OrderBy: orders,
Separator: node.Separator,
}
}
// Format formats the node.
func (node *ValuesFuncExpr) Format(buf *TrackedBuffer) {
// Function names should not be back-quoted even
// if they match a reserved word. So, print the
// name as is.
if node.Resolved != nil {
buf.Myprintf("%v", node.Resolved)
} else {
buf.Myprintf("values(%s)", node.Name.String())
}
}
func (node *ValuesFuncExpr) clone() Expr {
return &ValuesFuncExpr{
Name: node.Name,
Resolved: CloneExpr(node.Resolved),
}
}
// Format formats the node.
func (node *ConvertExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("convert(%v, %v)", node.Expr, node.Type)
}
func (node *ConvertExpr) clone() Expr {
return &ConvertExpr{
Expr: CloneExpr(node.Expr),
Type: node.Type,
}
}
// Format formats the node.
func (node *ConvertUsingExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("convert(%v using %s)", node.Expr, node.Type)
}
func (node *ConvertUsingExpr) clone() Expr {
return &ConvertUsingExpr{
Expr: CloneExpr(node.Expr),
Type: node.Type,
}
}
// Format formats the node.
func (node *ConvertType) Format(buf *TrackedBuffer) {
buf.Myprintf("%s", node.Type)
if node.Length != nil {
buf.Myprintf("(%v", node.Length)
if node.Scale != nil {
buf.Myprintf(", %v", node.Scale)
}
buf.Myprintf(")")
}
if node.Charset != "" {
buf.Myprintf("%s %s", node.Operator, node.Charset)
}
}
// Format formats the node
func (node *MatchExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("match(%v) against (%v%s)", node.Columns, node.Expr, node.Option)
}
func (node *MatchExpr) clone() Expr {
var exprs SelectExprs
for _, e := range node.Columns {
exp := CloneSelectExpr(e)
exprs = append(exprs, exp)
}
return &MatchExpr{
Columns: exprs,
Expr: CloneExpr(node.Expr),
Option: node.Option,
}
}
// Format formats the node.
func (node *CaseExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("case ")
if node.Expr != nil {
buf.Myprintf("%v ", node.Expr)
}
for _, when := range node.Whens {
buf.Myprintf("%v ", when)
}
if node.Else != nil {
buf.Myprintf("else %v ", node.Else)
}
buf.Myprintf("end")
}
func (node *CaseExpr) clone() Expr {
var whens []*When
for _, when := range node.Whens {
w := &When{
Cond: CloneExpr(when.Cond),
Val: CloneExpr(when.Val),
}
whens = append(whens, w)
}
return &CaseExpr{
Expr: CloneExpr(node.Expr),
Whens: whens,
Else: CloneExpr(node.Else),
}
}
// Format formats the node.
func (node *Default) Format(buf *TrackedBuffer) {
buf.Myprintf("default")
if node.ColName != "" {
buf.Myprintf("(%s)", node.ColName)
}
}
func (node *Default) clone() Expr {
return &Default{
ColName: node.ColName,
}
}
// Format formats the node.
func (node *When) Format(buf *TrackedBuffer) {
buf.Myprintf("when %v then %v", node.Cond, node.Val)
}
// Format formats the node.
func (node GroupBy) Format(buf *TrackedBuffer) {
prefix := " group by "
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node OrderBy) Format(buf *TrackedBuffer) {
prefix := " order by "
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node *Order) Format(buf *TrackedBuffer) {
if node, ok := node.Expr.(*NullVal); ok {
buf.Myprintf("%v", node)
return
}
buf.Myprintf("%v %s", node.Expr, node.Direction)
}
// Format formats the node.
func (node *Limit) Format(buf *TrackedBuffer) {
if node == nil {
return
}
buf.Myprintf(" limit ")
if node.Offset != nil {
buf.Myprintf("%v, ", node.Offset)
}
buf.Myprintf("%v", node.Rowcount)
}
// Format formats the node.
func (node Values) Format(buf *TrackedBuffer) {
prefix := "values "
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node UpdateExprs) Format(buf *TrackedBuffer) {
var prefix string
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node *UpdateExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%v = %v", node.Name, node.Expr)
}
// Format formats the node.
func (node OnDup) Format(buf *TrackedBuffer) {
if node == nil {
return
}
buf.Myprintf(" on duplicate key update %v", UpdateExprs(node))
}
// Format formats the node.
func (node SetExprs) Format(buf *TrackedBuffer) {
var prefix string
for _, n := range node {
buf.Myprintf("%s%v", prefix, n)
prefix = ", "
}
}
// Format formats the node.
func (node *SetExpr) Format(buf *TrackedBuffer) {
if node.Scope != "" {
buf.WriteString(node.Scope)
buf.WriteString(" ")
}
// We don't have to backtick set variable names.
switch {
case node.Type.EqualString("charset") || node.Type.EqualString("names") || node.Type.EqualString("transaction"):
buf.Myprintf("%s %v", node.Type.String(), node.Val)
default:
buf.Myprintf("%s = %v", node.Type.String(), node.Val)
}
}
// Format formats the node.
func (node *OptVal) Format(buf *TrackedBuffer) {
buf.Myprintf("%v", node.Value)
}
// Format formats the node.
func (node *TxnVal) Format(buf *TrackedBuffer) {
var prefix string
if node.Level != "" {
buf.WriteString("isolation level " + node.Level)
prefix = ", "
}
if node.Mode != "" {
buf.Myprintf("%s%s", prefix, node.Mode)
}
}
// Format formats the node.
func (node ColIdent) Format(buf *TrackedBuffer) {
formatID(buf, node.val, node.Lowered())
}
// Format formats the node.
func (node TableIdent) Format(buf *TrackedBuffer) {
formatID(buf, node.v, strings.ToLower(node.v))
}
// Format formats the node.
func (node *Radon) Format(buf *TrackedBuffer) {
switch node.Action {
case AttachListStr:
buf.Myprintf("radon %s", node.Action)
case AttachStr, DetachStr:
buf.Myprintf("radon %s %v", node.Action, node.Row)
case ReshardStr:
buf.Myprintf("radon %s %v to %v", node.Action, node.Table, node.NewName)
case CleanupStr:
buf.Myprintf("radon %s", node.Action)
}
}
// Format formats the node.
func (node *Explain) Format(buf *TrackedBuffer) {
buf.WriteString("explain")
}
// Format formats the node.
func (node *Kill) Format(buf *TrackedBuffer) {
buf.Myprintf("kill %s", node.QueryID.raw)
}
// Format formats the node.
func (node *Transaction) Format(buf *TrackedBuffer) {
switch node.Action {
case StartTxnStr:
buf.WriteString(StartTxnStr)
case BeginTxnStr:
buf.WriteString(BeginTxnStr)
case RollbackTxnStr:
buf.WriteString(RollbackTxnStr)
case CommitTxnStr:
buf.WriteString(CommitTxnStr)
}
}
// Format formats the node.
func (node *Xa) Format(buf *TrackedBuffer) {
buf.WriteString("XA")
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。