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 }