001package gudusoft.gsqlparser.stmt.oceanbase; 002 003import gudusoft.gsqlparser.EDbVendor; 004import gudusoft.gsqlparser.ESqlStatementType; 005import gudusoft.gsqlparser.TCustomSqlStatement; 006import gudusoft.gsqlparser.nodes.TObjectName; 007import gudusoft.gsqlparser.nodes.TParseTreeVisitor; 008import gudusoft.gsqlparser.nodes.oceanbase.TOceanbaseCreateTenantSqlNode; 009import gudusoft.gsqlparser.nodes.oceanbase.TOceanbaseTenantOption; 010 011import java.util.ArrayList; 012 013/** 014 * OceanBase {@code CREATE TENANT} statement (Phase 4 Batch 1). 015 * 016 * <p>Exposes the parsed tenant name, {@code IF NOT EXISTS} flag, and the 017 * full tenant option list. Typed convenience accessors 018 * ({@link #getPrimaryZone()}, {@link #getLocality()}, 019 * {@link #getCharset()}, {@link #getCompatibilityMode()}, 020 * {@link #getResourcePoolList()}) scan the option list on demand so the 021 * core is not coupled to the exhaustive OceanBase option vocabulary and 022 * future option additions need no code change here. 023 * 024 * <p>Statements of this shape are tagged 025 * {@link ESqlStatementType#sstoceanbase_create_tenant} per ADR-8. 026 * 027 * @see TAlterTenantSqlStatement 028 * @see TDropTenantSqlStatement 029 * @since 4.0.1.4 030 */ 031public class TCreateTenantSqlStatement extends TCustomSqlStatement { 032 033 private TObjectName tenantName; 034 private boolean ifNotExists; 035 private ArrayList<TOceanbaseTenantOption> tenantOptions 036 = new ArrayList<TOceanbaseTenantOption>(); 037 038 public TCreateTenantSqlStatement(EDbVendor dbvendor) { 039 super(dbvendor); 040 this.sqlstatementtype = ESqlStatementType.sstoceanbase_create_tenant; 041 } 042 043 public TObjectName getTenantName() { 044 return tenantName; 045 } 046 047 public boolean isIfNotExists() { 048 return ifNotExists; 049 } 050 051 public ArrayList<TOceanbaseTenantOption> getTenantOptions() { 052 return tenantOptions; 053 } 054 055 // ----------------------------------------------------------------- 056 // Typed convenience accessors — scan the option list on demand. 057 // ----------------------------------------------------------------- 058 059 /** 060 * @return the first value of the {@code PRIMARY_ZONE} option, or 061 * {@code null} when not specified. 062 */ 063 public TObjectName getPrimaryZone() { 064 return firstValueOfOption("PRIMARY_ZONE"); 065 } 066 067 /** 068 * @return the first value of the {@code LOCALITY} option, or 069 * {@code null} when not specified. 070 */ 071 public TObjectName getLocality() { 072 return firstValueOfOption("LOCALITY"); 073 } 074 075 /** 076 * @return the first value of the {@code CHARSET} option, or 077 * {@code null} when not specified. 078 */ 079 public TObjectName getCharset() { 080 return firstValueOfOption("CHARSET"); 081 } 082 083 /** 084 * @return the value of {@code SET ob_compatibility_mode = '...'} when 085 * present among the tenant options, or {@code null} when not 086 * specified. This is how callers distinguish a MySQL-mode 087 * tenant from an Oracle-mode tenant at the DDL level. 088 */ 089 public TObjectName getCompatibilityMode() { 090 for (TOceanbaseTenantOption opt : tenantOptions) { 091 if (opt == null || opt.getName() == null) continue; 092 if (opt.isSetVariable() 093 && "OB_COMPATIBILITY_MODE".equals(opt.getName())) { 094 return opt.getFirstValue(); 095 } 096 } 097 return null; 098 } 099 100 /** 101 * @return the list of pool names listed in the 102 * {@code RESOURCE_POOL_LIST = ('p1', 'p2', ...)} option, or an 103 * empty list when not specified. 104 */ 105 public ArrayList<TObjectName> getResourcePoolList() { 106 for (TOceanbaseTenantOption opt : tenantOptions) { 107 if (opt == null || opt.getName() == null) continue; 108 if (!opt.isSetVariable() 109 && "RESOURCE_POOL_LIST".equals(opt.getName())) { 110 return opt.getValues(); 111 } 112 } 113 return new ArrayList<TObjectName>(); 114 } 115 116 private TObjectName firstValueOfOption(String canonicalName) { 117 for (TOceanbaseTenantOption opt : tenantOptions) { 118 if (opt == null || opt.getName() == null) continue; 119 if (!opt.isSetVariable() && canonicalName.equals(opt.getName())) { 120 return opt.getFirstValue(); 121 } 122 } 123 return null; 124 } 125 126 // ----------------------------------------------------------------- 127 // Framework overrides 128 // ----------------------------------------------------------------- 129 130 @Override 131 public int doParseStatement(TCustomSqlStatement psql) { 132 if (rootNode == null) return -1; 133 super.doParseStatement(psql); 134 TOceanbaseCreateTenantSqlNode node = (TOceanbaseCreateTenantSqlNode) rootNode; 135 this.tenantName = node.getTenantName(); 136 this.ifNotExists = node.isIfNotExists(); 137 this.tenantOptions = node.getTenantOptions(); 138 return 0; 139 } 140 141 @Override 142 public void accept(TParseTreeVisitor v) { 143 v.preVisit(this); 144 v.postVisit(this); 145 } 146 147 @Override 148 public void acceptChildren(TParseTreeVisitor v) { 149 v.preVisit(this); 150 v.postVisit(this); 151 } 152}