github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/stmt_kind.go (about)

     1  // Copyright 2021 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package frontend
    16  
    17  import (
    18  	"context"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql"
    21  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    22  )
    23  
    24  // IsAdministrativeStatement checks the statement is the administrative statement.
    25  func IsAdministrativeStatement(stmt tree.Statement) bool {
    26  	switch st := stmt.(type) {
    27  	case *tree.CreateAccount, *tree.DropAccount, *tree.AlterAccount,
    28  		*tree.CreateUser, *tree.DropUser, *tree.AlterUser,
    29  		*tree.CreateRole, *tree.DropRole,
    30  		*tree.Revoke, *tree.Grant,
    31  		*tree.SetDefaultRole, *tree.SetRole, *tree.SetPassword:
    32  		return true
    33  	case *tree.Use:
    34  		return st.IsUseRole()
    35  	}
    36  	return false
    37  }
    38  
    39  // IsParameterModificationStatement checks the statement is the statement of parameter modification statement.
    40  func IsParameterModificationStatement(stmt tree.Statement) bool {
    41  	switch stmt.(type) {
    42  	case *tree.SetVar:
    43  		return true
    44  	}
    45  	return false
    46  }
    47  
    48  // IsPrepareStatement checks the statement is the Prepare statement.
    49  func IsPrepareStatement(stmt tree.Statement) bool {
    50  	switch stmt.(type) {
    51  	case *tree.PrepareStmt, *tree.PrepareString:
    52  		return true
    53  	}
    54  	return false
    55  }
    56  
    57  // IsDDL checks the statement is the DDL statement.
    58  func IsDDL(stmt tree.Statement) bool {
    59  	switch stmt.(type) {
    60  	case *tree.CreateTable, *tree.DropTable,
    61  		*tree.CreateView, *tree.DropView, *tree.AlterView, *tree.AlterTable,
    62  		*tree.CreateDatabase, *tree.DropDatabase, *tree.CreateSequence, *tree.DropSequence,
    63  		*tree.CreateIndex, *tree.DropIndex, *tree.TruncateTable:
    64  		return true
    65  	}
    66  	return false
    67  }
    68  
    69  // IsDropStatement checks the statement is the drop statement.
    70  func IsDropStatement(stmt tree.Statement) bool {
    71  	switch stmt.(type) {
    72  	case *tree.DropDatabase, *tree.DropTable, *tree.DropView, *tree.DropIndex, *tree.DropSequence:
    73  		return true
    74  	}
    75  	return false
    76  }
    77  
    78  func IsCreateDropDatabase(stmt tree.Statement) bool {
    79  	switch stmt.(type) {
    80  	case *tree.CreateDatabase, *tree.DropDatabase:
    81  		return true
    82  	}
    83  	return false
    84  }
    85  
    86  func IsCreateDropSequence(stmt tree.Statement) bool {
    87  	switch stmt.(type) {
    88  	case *tree.CreateSequence, *tree.DropSequence:
    89  		return true
    90  	}
    91  	return false
    92  }
    93  
    94  /*
    95  NeedToBeCommittedInActiveTransaction checks the statement that need to be committed
    96  in an active transaction.
    97  
    98  Currently, it includes the drop statement, the administration statement ,
    99  
   100  	the parameter modification statement.
   101  */
   102  func NeedToBeCommittedInActiveTransaction(stmt tree.Statement) bool {
   103  	if stmt == nil {
   104  		return false
   105  	}
   106  	return IsCreateDropSequence(stmt) || IsAdministrativeStatement(stmt) || IsParameterModificationStatement(stmt)
   107  }
   108  
   109  /*
   110  StatementCanBeExecutedInUncommittedTransaction checks the statement can be executed in an active transaction.
   111  
   112  Cases    | set Autocommit = 1/0 | BEGIN statement |
   113  ---------------------------------------------------
   114  Case1      1                       Yes
   115  Case2      1                       No
   116  Case3      0                       Yes
   117  Case4      0                       No
   118  ---------------------------------------------------
   119  
   120  If it is Case1,Case3, Then
   121  
   122  	Create/Drop database reports error
   123  
   124  If it is Case2, Then
   125  
   126  	Create/Drop database as other statement.
   127  
   128  If it is Case4, Then
   129  
   130  	Create/Drop database commits current txn. a new txn for the next statement if needed.
   131  */
   132  func statementCanBeExecutedInUncommittedTransaction(ctx context.Context, ses FeSession, stmt tree.Statement) (bool, error) {
   133  	switch st := stmt.(type) {
   134  	//ddl statement
   135  	case *tree.CreateTable, *tree.CreateIndex, *tree.CreateView, *tree.AlterView, *tree.AlterTable:
   136  		if createTblStmt, ok := stmt.(*tree.CreateTable); ok && createTblStmt.IsAsSelect {
   137  			return false, nil
   138  		}
   139  		return true, nil
   140  	case *tree.CreateDatabase, *tree.DropDatabase:
   141  		return true, nil
   142  	case *tree.CreateSequence: //Case1, Case3 above
   143  		return ses.IsBackgroundSession() || !ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), nil
   144  		//dml statement
   145  	case *tree.Insert, *tree.Update, *tree.Delete, *tree.Select, *tree.Load, *tree.MoDump, *tree.ValuesStatement, *tree.Replace:
   146  		return true, nil
   147  		//transaction
   148  	case *tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction:
   149  		return true, nil
   150  		//show
   151  	case *tree.ShowCreateTable,
   152  		*tree.ShowCreateView,
   153  		*tree.ShowCreateDatabase,
   154  		*tree.ShowColumns,
   155  		*tree.ShowDatabases,
   156  		*tree.ShowTarget,
   157  		*tree.ShowTableStatus,
   158  		*tree.ShowGrants,
   159  		*tree.ShowTables,
   160  		*tree.ShowSequences,
   161  		*tree.ShowProcessList,
   162  		*tree.ShowErrors,
   163  		*tree.ShowWarnings,
   164  		*tree.ShowCollation,
   165  		*tree.ShowVariables,
   166  		*tree.ShowStatus,
   167  		*tree.ShowIndex,
   168  		*tree.ShowFunctionOrProcedureStatus,
   169  		*tree.ShowNodeList,
   170  		*tree.ShowLocks,
   171  		*tree.ShowTableNumber,
   172  		*tree.ShowColumnNumber,
   173  		*tree.ShowTableValues,
   174  		*tree.ShowAccounts,
   175  		*tree.ShowPublications,
   176  		*tree.ShowSubscriptions,
   177  		*tree.ShowCreatePublications,
   178  		*tree.ShowBackendServers,
   179  		*tree.ShowAccountUpgrade,
   180  		*tree.ShowConnectors:
   181  		return true, nil
   182  		//others
   183  	case *tree.ExplainStmt, *tree.ExplainAnalyze, *tree.ExplainFor, *InternalCmdFieldList:
   184  		return true, nil
   185  	case *tree.PrepareStmt:
   186  		return statementCanBeExecutedInUncommittedTransaction(ctx, ses, st.Stmt)
   187  	case *tree.PrepareString:
   188  		v, err := ses.GetGlobalVar(ctx, "lower_case_table_names")
   189  		if err != nil {
   190  			return false, err
   191  		}
   192  		preStmt, err := mysql.ParseOne(ctx, st.Sql, v.(int64), 0)
   193  		defer func() {
   194  			preStmt.Free()
   195  		}()
   196  		if err != nil {
   197  			return false, err
   198  		}
   199  		return statementCanBeExecutedInUncommittedTransaction(ctx, ses, preStmt)
   200  	case *tree.Execute:
   201  		preName := string(st.Name)
   202  		preStmt, err := ses.GetPrepareStmt(ctx, preName)
   203  		if err != nil {
   204  			return false, err
   205  		}
   206  		return statementCanBeExecutedInUncommittedTransaction(ctx, ses, preStmt.PrepareStmt)
   207  	case *tree.Deallocate, *tree.Reset:
   208  		return true, nil
   209  	case *tree.Use:
   210  		/*
   211  			These statements can not be executed in an uncommitted transaction:
   212  				USE SECONDARY ROLE { ALL | NONE }
   213  				USE ROLE role;
   214  		*/
   215  		return !st.IsUseRole(), nil
   216  	case *tree.DropTable, *tree.DropIndex, *tree.DropView, *tree.TruncateTable:
   217  		return true, nil
   218  	case *tree.DropSequence: //Case1, Case3 above
   219  		//background transaction can execute the DROPxxx in one transaction
   220  		return ses.IsBackgroundSession() || !ses.GetTxnHandler().OptionBitsIsSet(OPTION_BEGIN), nil
   221  	case *tree.SetVar:
   222  		return true, nil
   223  	}
   224  
   225  	return false, nil
   226  }