Skip to content

Commit

Permalink
improve schema api for catalog table
Browse files Browse the repository at this point in the history
  • Loading branch information
JNSimba committed Dec 25, 2024
1 parent b5644fd commit 597ff99
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,13 @@ protected void checkDbAuth(UserIdentity currentUser, String db, PrivPredicate pr

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");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,26 @@

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;
Expand All @@ -54,24 +60,33 @@
@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) {
executeCheckPassword(request, response);
// 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();
Expand All @@ -97,7 +112,9 @@ protected Object schema(
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
Expand Down
60 changes: 60 additions & 0 deletions regression-test/suites/http_rest_api/get/test_schema_api.groovy
Original file line number Diff line number Diff line change
@@ -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"))

}

0 comments on commit 597ff99

Please sign in to comment.