util.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 2018 PingCAP, Inc.
  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. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package ast
  14. import "math"
  15. // UnspecifiedSize is unspecified size.
  16. const (
  17. UnspecifiedSize = math.MaxUint64
  18. )
  19. // IsReadOnly checks whether the input ast is readOnly.
  20. func IsReadOnly(node Node) bool {
  21. switch st := node.(type) {
  22. case *SelectStmt:
  23. if st.LockInfo != nil {
  24. switch st.LockInfo.LockType {
  25. case SelectLockForUpdate, SelectLockForUpdateNoWait, SelectLockForUpdateWaitN:
  26. return false
  27. }
  28. }
  29. checker := readOnlyChecker{
  30. readOnly: true,
  31. }
  32. node.Accept(&checker)
  33. return checker.readOnly
  34. case *ExplainStmt:
  35. return !st.Analyze || IsReadOnly(st.Stmt)
  36. case *DoStmt, *ShowStmt:
  37. return true
  38. case *SetOprStmt:
  39. for _, sel := range node.(*SetOprStmt).SelectList.Selects {
  40. if !IsReadOnly(sel) {
  41. return false
  42. }
  43. }
  44. return true
  45. case *SetOprSelectList:
  46. for _, sel := range node.(*SetOprSelectList).Selects {
  47. if !IsReadOnly(sel) {
  48. return false
  49. }
  50. }
  51. return true
  52. default:
  53. return false
  54. }
  55. }
  56. // readOnlyChecker checks whether a query's ast is readonly, if it satisfied
  57. // 1. selectstmt;
  58. // 2. need not to set var;
  59. // it is readonly statement.
  60. type readOnlyChecker struct {
  61. readOnly bool
  62. }
  63. // Enter implements Visitor interface.
  64. func (checker *readOnlyChecker) Enter(in Node) (out Node, skipChildren bool) {
  65. switch node := in.(type) {
  66. case *VariableExpr:
  67. // like func rewriteVariable(), this stands for SetVar.
  68. if !node.IsSystem && node.Value != nil {
  69. checker.readOnly = false
  70. return in, true
  71. }
  72. }
  73. return in, false
  74. }
  75. // Leave implements Visitor interface.
  76. func (checker *readOnlyChecker) Leave(in Node) (out Node, ok bool) {
  77. return in, checker.readOnly
  78. }