This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new ff68859546e branch-2.1: [improvement](http) improve table schema api 
for catalog table #45933 (#45982)
ff68859546e is described below

commit ff68859546eadde9e20d8120c953bfbc83edd8c7
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jan 3 16:40:12 2025 +0800

    branch-2.1: [improvement](http) improve table schema api for catalog table 
#45933 (#45982)
    
    Cherry-picked from #45933
    
    Co-authored-by: wudi <w...@selectdb.com>
---
 .../doris/httpv2/controller/BaseController.java    | 10 +++-
 .../doris/httpv2/rest/RestBaseController.java      |  1 +
 .../doris/httpv2/rest/TableSchemaAction.java       | 39 ++++++++++----
 .../http_rest_api/get/test_schema_api.groovy       | 60 ++++++++++++++++++++++
 4 files changed, 98 insertions(+), 12 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
index 026b1f8bda3..60fc9258717 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/BaseController.java
@@ -117,7 +117,7 @@ public class BaseController {
     }
 
     private ActionAuthorizationInfo checkCookie(HttpServletRequest request, 
HttpServletResponse response,
-                                                boolean checkAuth) {
+            boolean checkAuth) {
         List<String> sessionIds = getCookieValues(request, PALO_SESSION_ID, 
response);
         if (sessionIds.isEmpty()) {
             return null;
@@ -218,8 +218,14 @@ public class BaseController {
 
     protected void checkTblAuth(UserIdentity currentUser, String db, String 
tbl, PrivPredicate predicate)
             throws UnauthorizedException {
+        checkTblAuth(currentUser, InternalCatalog.INTERNAL_CATALOG_NAME, db, 
tbl, predicate);
+    }
+
+    protected void checkTblAuth(UserIdentity currentUser, String catalog, 
String db, String tbl,
+            PrivPredicate predicate)
+            throws UnauthorizedException {
         if (!Env.getCurrentEnv().getAccessManager()
-                .checkTblPriv(currentUser, 
InternalCatalog.INTERNAL_CATALOG_NAME, db, tbl, predicate)) {
+                .checkTblPriv(currentUser, catalog, db, tbl, predicate)) {
             throw new UnauthorizedException("Access denied; you need (at least 
one of) the "
                     + predicate.getPrivs().toString() + " privilege(s) for 
this operation");
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/RestBaseController.java 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/RestBaseController.java
index 5621ffaccde..bf07eda4f8d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/RestBaseController.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/RestBaseController.java
@@ -49,6 +49,7 @@ import javax.servlet.http.HttpServletResponse;
 public class RestBaseController extends BaseController {
 
     protected static final String NS_KEY = "ns";
+    protected static final String CATALOG_KEY = "catalog";
     protected static final String DB_KEY = "db";
     protected static final String TABLE_KEY = "table";
     protected static final String LABEL_KEY = "label";
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/TableSchemaAction.java 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/TableSchemaAction.java
index ae1b3956179..0f362b4aad8 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/TableSchemaAction.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/rest/TableSchemaAction.java
@@ -19,20 +19,26 @@ package org.apache.doris.httpv2.rest;
 
 import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.Database;
+import org.apache.doris.catalog.DatabaseIf;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.OlapTable;
 import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.catalog.Table;
+import org.apache.doris.catalog.TableIf;
 import org.apache.doris.catalog.Type;
+import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.DorisHttpException;
 import org.apache.doris.common.MetaNotFoundException;
+import org.apache.doris.datasource.CatalogIf;
+import org.apache.doris.datasource.InternalCatalog;
 import org.apache.doris.httpv2.entity.ResponseEntityBuilder;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -54,8 +60,10 @@ import javax.servlet.http.HttpServletResponse;
 @RestController
 public class TableSchemaAction extends RestBaseController {
 
-    @RequestMapping(path = "/api/{" + DB_KEY + "}/{" + TABLE_KEY + 
"}/_schema", method = RequestMethod.GET)
+    @RequestMapping(path = {"/api/{" + DB_KEY + "}/{" + TABLE_KEY + 
"}/_schema",
+            "/api/{" + CATALOG_KEY + "}/{" + DB_KEY + "}/{" + TABLE_KEY + 
"}/_schema"}, method = RequestMethod.GET)
     protected Object schema(
+            @PathVariable(value = CATALOG_KEY, required = false) String 
catalogName,
             @PathVariable(value = DB_KEY) final String dbName,
             @PathVariable(value = TABLE_KEY) final String tblName,
             HttpServletRequest request, HttpServletResponse response) {
@@ -63,15 +71,22 @@ public class TableSchemaAction extends RestBaseController {
         // just allocate 2 slot for top holder map
         Map<String, Object> resultMap = new HashMap<>(2);
 
+        if (StringUtils.isBlank(catalogName)) {
+            catalogName = InternalCatalog.INTERNAL_CATALOG_NAME;
+        }
+
         try {
             String fullDbName = getFullDbName(dbName);
             // check privilege for select, otherwise return 401 HTTP status
-            checkTblAuth(ConnectContext.get().getCurrentUserIdentity(), 
fullDbName, tblName, PrivPredicate.SELECT);
-            OlapTable table;
+            checkTblAuth(ConnectContext.get().getCurrentUserIdentity(), 
catalogName, fullDbName, tblName,
+                    PrivPredicate.SELECT);
+            TableIf table;
             try {
-                Database db = 
Env.getCurrentInternalCatalog().getDbOrMetaException(fullDbName);
-                table = (OlapTable) db.getTableOrMetaException(tblName, 
Table.TableType.OLAP);
-            } catch (MetaNotFoundException e) {
+                CatalogIf catalog = StringUtils.isNotBlank(catalogName) ? 
Env.getCurrentEnv().getCatalogMgr()
+                        .getCatalogOrAnalysisException(catalogName) : 
Env.getCurrentInternalCatalog();
+                DatabaseIf db = catalog.getDbOrMetaException(fullDbName);
+                table = db.getTableOrMetaException(tblName);
+            } catch (MetaNotFoundException | AnalysisException e) {
                 return ResponseEntityBuilder.okWithCommonError(e.getMessage());
             }
             table.readLock();
@@ -97,7 +112,9 @@ public class TableSchemaAction extends RestBaseController {
                         propList.add(baseInfo);
                     }
                     resultMap.put("status", 200);
-                    resultMap.put("keysType", table.getKeysType().name());
+                    if (table instanceof OlapTable) {
+                        resultMap.put("keysType", ((OlapTable) 
table).getKeysType().name());
+                    }
                     resultMap.put("properties", propList);
                 } catch (Exception e) {
                     // Transform the general Exception to custom 
DorisHttpException
@@ -115,6 +132,7 @@ public class TableSchemaAction extends RestBaseController {
         return ResponseEntityBuilder.ok(resultMap);
     }
 
+
     private static class DDLRequestBody {
         public Boolean isDropColumn;
         public String columnName;
@@ -128,7 +146,7 @@ public class TableSchemaAction extends RestBaseController {
      * }
      */
     @RequestMapping(path = "/api/enable_light_schema_change/{" + DB_KEY
-                    + "}/{" + TABLE_KEY + "}", method = { RequestMethod.GET })
+            + "}/{" + TABLE_KEY + "}", method = {RequestMethod.GET})
     public Object columnChangeCanSync(
             @PathVariable(value = DB_KEY) String dbName,
             @PathVariable(value = TABLE_KEY) String tableName,
@@ -145,7 +163,8 @@ public class TableSchemaAction extends RestBaseController {
         if (!table.getEnableLightSchemaChange()) {
             return ResponseEntityBuilder.okWithCommonError("table " + 
tableName + " disable light schema change");
         }
-        java.lang.reflect.Type type = new TypeToken<DDLRequestBody>() 
{}.getType();
+        java.lang.reflect.Type type = new TypeToken<DDLRequestBody>() {
+        }.getType();
         DDLRequestBody ddlRequestBody = new Gson().fromJson(body, type);
         if (ddlRequestBody.isDropColumn) {
             boolean enableLightSchemaChange = true;
@@ -165,7 +184,7 @@ public class TableSchemaAction extends RestBaseController {
             }
             if (!enableLightSchemaChange) {
                 return ResponseEntityBuilder.okWithCommonError("Column " + 
ddlRequestBody.columnName
-                                + " is primary key in materializedIndex that 
can't do the light schema change");
+                        + " is primary key in materializedIndex that can't do 
the light schema change");
             }
         }
         return ResponseEntityBuilder.ok();
diff --git a/regression-test/suites/http_rest_api/get/test_schema_api.groovy 
b/regression-test/suites/http_rest_api/get/test_schema_api.groovy
new file mode 100644
index 00000000000..937b35d4832
--- /dev/null
+++ b/regression-test/suites/http_rest_api/get/test_schema_api.groovy
@@ -0,0 +1,60 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+import org.apache.doris.regression.util.Http
+
+suite("test_schema_api") {
+
+    def thisDb = sql """select database()""";
+    thisDb = thisDb[0][0];
+    logger.info("current database is ${thisDb}");
+
+    def tbName = "test_schema_api"
+    sql "DROP TABLE IF EXISTS ${tbName}"
+    sql """
+        CREATE TABLE ${tbName}
+        (
+            `id` LARGEINT NOT NULL COMMENT "id",
+            `c1` DECIMAL(10, 2) COMMENT "decimal columns",
+            `c2` date NOT NULL COMMENT "date columns",
+            `c3` VARCHAR(20) COMMENT "nullable columns",
+            `c4` VARCHAR COMMENT "varchar columns",
+            `c5` BIGINT DEFAULT "0" COMMENT "test columns"
+        )
+        UNIQUE KEY(`id`)
+        DISTRIBUTED BY HASH(`id`) BUCKETS 8
+        PROPERTIES (
+        "replication_allocation" = "tag.location.default: 1"
+        );
+        """
+
+    //exist table
+    def url = String.format("http://%s/api/%s/%s/_schema";, 
context.config.feHttpAddress, thisDb, tbName)
+    def result = Http.GET(url, true)
+    assertTrue(result.code == 0)
+    assertEquals(result.msg, "success")
+    // parsing
+    def resultList = result.data.properties
+    assertTrue(resultList.size() == 6)
+
+    // not exist catalog
+    def url2 = String.format("http://%s/api/%s/%s/%s/_schema";, 
context.config.feHttpAddress, "notexistctl", thisDb, tbName)
+    def result2 = Http.GET(url2, true)
+    assertTrue(result2.code != 0)
+    assertTrue(result2.data.contains("Unknown catalog"))
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to