join.py 18.3 KB
Newer Older
C
cpwu 已提交
1 2
import datetime

C
cpwu 已提交
3 4
from dataclasses import dataclass, field
from typing import List, Any, Tuple
C
cpwu 已提交
5 6 7 8 9
from util.log import *
from util.sql import *
from util.cases import *
from util.dnodes import *

C
cpwu 已提交
10
PRIMARY_COL = "ts"
C
cpwu 已提交
11

C
cpwu 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
INT_COL = "c_int"
BINT_COL = "c_bint"
SINT_COL = "c_sint"
TINT_COL = "c_tint"
FLOAT_COL = "c_float"
DOUBLE_COL = "c_double"
BOOL_COL = "c_bool"
TINT_UN_COL = "c_utint"
SINT_UN_COL = "c_usint"
BINT_UN_COL = "c_ubint"
INT_UN_COL = "c_uint"
BINARY_COL = "c_binary"
NCHAR_COL = "c_nchar"
TS_COL = "c_ts"

NUM_COL = [INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, ]
CHAR_COL = [BINARY_COL, NCHAR_COL, ]
BOOLEAN_COL = [BOOL_COL, ]
TS_TYPE_COL = [TS_COL, ]

INT_TAG = "t_int"

ALL_COL = [PRIMARY_COL, INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, BINARY_COL, NCHAR_COL, BOOL_COL, TS_COL]
TAG_COL = [INT_TAG]
# insert data args:
TIME_STEP = 10000
NOW = int(datetime.datetime.timestamp(datetime.datetime.now()) * 1000)

# init db/table
DBNAME  = "db"
STBNAME = "stb1"
CTBNAME = "ct1"
NTBNAME = "nt1"

@dataclass
class DataSet:
    ts_data     : List[int]     = field(default_factory=list)
    int_data    : List[int]     = field(default_factory=list)
    bint_data   : List[int]     = field(default_factory=list)
    sint_data   : List[int]     = field(default_factory=list)
    tint_data   : List[int]     = field(default_factory=list)
    int_un_data : List[int]     = field(default_factory=list)
    bint_un_data: List[int]     = field(default_factory=list)
    sint_un_data: List[int]     = field(default_factory=list)
    tint_un_data: List[int]     = field(default_factory=list)
    float_data  : List[float]   = field(default_factory=list)
    double_data : List[float]   = field(default_factory=list)
    bool_data   : List[int]     = field(default_factory=list)
    binary_data : List[str]     = field(default_factory=list)
    nchar_data  : List[str]     = field(default_factory=list)
C
cpwu 已提交
62 63 64 65 66 67


class TDTestCase:

    def init(self, conn, logSql):
        tdLog.debug(f"start to excute {__file__}")
C
cpwu 已提交
68
        tdSql.init(conn.cursor(), False)
C
cpwu 已提交
69

C
cpwu 已提交
70 71
    def __query_condition(self,tbname):
        query_condition = []
C
cpwu 已提交
72
        for char_col in CHAR_COL:
C
cpwu 已提交
73
            query_condition.extend(
C
cpwu 已提交
74
                (
C
cpwu 已提交
75
                    f"{tbname}.{char_col}",
C
cpwu 已提交
76
                    # f"upper( {tbname}.{char_col} )",
C
cpwu 已提交
77 78
                )
            )
C
cpwu 已提交
79 80 81 82
            query_condition.extend( f"cast( {tbname}.{un_char_col} as binary(16) ) " for un_char_col in NUM_COL)
        for num_col in NUM_COL:
            query_condition.extend(
                (
C
cpwu 已提交
83
                    f"sin( {tbname}.{num_col} )",
C
cpwu 已提交
84 85 86 87
                )
            )
            query_condition.extend( f"{tbname}.{num_col} + {tbname}.{num_col_1} " for num_col_1 in NUM_COL )

C
cpwu 已提交
88
        query_condition.append(''' "test1234!@#$%^&*():'><?/.,][}{" ''')
C
cpwu 已提交
89 90 91

        return query_condition

C
cpwu 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
    def __join_condition(self, tb_list, filter=PRIMARY_COL, INNER=False):
        table_reference = tb_list[0]
        join_condition = table_reference
        join = "inner join" if INNER else "join"
        for i in range(len(tb_list[1:])):
            join_condition += f" {join} {tb_list[i+1]} on {table_reference}.{filter}={tb_list[i+1]}.{filter}"

        return join_condition

    def __where_condition(self, col=None, tbname=None, query_conditon=None):
        if query_conditon and isinstance(query_conditon, str):
            if query_conditon.startswith("count"):
                query_conditon = query_conditon[6:-1]
            elif query_conditon.startswith("max"):
                query_conditon = query_conditon[4:-1]
            elif query_conditon.startswith("sum"):
                query_conditon = query_conditon[4:-1]
            elif query_conditon.startswith("min"):
                query_conditon = query_conditon[4:-1]

        if query_conditon:
            return f" where {query_conditon} is not null"
C
cpwu 已提交
114
        if col in NUM_COL:
C
cpwu 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
            return f" where abs( {tbname}.{col} ) >= 0"
        if col in CHAR_COL:
            return f" where lower( {tbname}.{col} ) like 'bina%' or lower( {tbname}.{col} ) like '_cha%' "
        if col in BOOLEAN_COL:
            return f" where {tbname}.{col} in (false, true)  "
        if col in TS_TYPE_COL or col in PRIMARY_COL:
            return f" where cast( {tbname}.{col} as binary(16) ) is not null "

        return ""

    def __group_condition(self, col, having = None):
        if isinstance(col, str):
            if col.startswith("count"):
                col = col[6:-1]
            elif col.startswith("max"):
                col = col[4:-1]
            elif col.startswith("sum"):
                col = col[4:-1]
            elif col.startswith("min"):
                col = col[4:-1]
C
cpwu 已提交
135
        return f" group by {col} having {having}" if having else f" group by {col} "
C
cpwu 已提交
136

C
cpwu 已提交
137 138 139 140 141 142 143 144
    def __gen_sql(self, select_clause, from_clause, where_condition="", group_condition=""):
        if isinstance(select_clause, str) and "on" not in from_clause and select_clause.split(".")[0] != from_clause.split(".")[0]:
            return
        return f"select {select_clause} from {from_clause} {where_condition} {group_condition}"

    @property
    def __join_tblist(self):
        return [
C
cpwu 已提交
145
            # ["ct1", "ct2"],
C
cpwu 已提交
146
            ["ct1", "ct4"],
C
cpwu 已提交
147
            ["ct1", "nt1"],
C
cpwu 已提交
148
            # ["ct2", "ct4"],
C
cpwu 已提交
149 150
            # ["ct2", "nt1"],
            # ["ct4", "nt1"],
C
cpwu 已提交
151
            # ["ct1", "ct2", "ct4"],
C
cpwu 已提交
152 153 154 155
            # ["ct1", "ct2", "nt1"],
            # ["ct1", "ct4", "nt1"],
            # ["ct2", "ct4", "nt1"],
            # ["ct1", "ct2", "ct4", "nt1"],
C
cpwu 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
        ]

    @property
    def __sqls_list(self):
        sqls = []
        __join_tblist = self.__join_tblist
        for join_tblist in __join_tblist:
            for join_tb in join_tblist:
                select_claus_list = self.__query_condition(join_tb)
                for select_claus in select_claus_list:
                    group_claus = self.__group_condition( col=select_claus)
                    where_claus = self.__where_condition( query_conditon=select_claus )
                    having_claus = self.__group_condition( col=select_claus, having=f"{select_claus} is not null" )
                    sqls.extend(
                        (
C
cpwu 已提交
171
                            # self.__gen_sql(select_claus, self.__join_condition(join_tblist), where_claus, group_claus),
C
cpwu 已提交
172 173
                            self.__gen_sql(select_claus, self.__join_condition(join_tblist), where_claus, having_claus),
                            self.__gen_sql(select_claus, self.__join_condition(join_tblist), where_claus),
C
cpwu 已提交
174
                            # self.__gen_sql(select_claus, self.__join_condition(join_tblist), group_claus),
C
cpwu 已提交
175 176
                            self.__gen_sql(select_claus, self.__join_condition(join_tblist), having_claus),
                            self.__gen_sql(select_claus, self.__join_condition(join_tblist)),
C
cpwu 已提交
177
                            # self.__gen_sql(select_claus, self.__join_condition(join_tblist, INNER=True), where_claus, group_claus),
C
cpwu 已提交
178 179 180
                            self.__gen_sql(select_claus, self.__join_condition(join_tblist, INNER=True), where_claus, having_claus),
                            self.__gen_sql(select_claus, self.__join_condition(join_tblist, INNER=True), where_claus, ),
                            self.__gen_sql(select_claus, self.__join_condition(join_tblist, INNER=True), having_claus ),
C
cpwu 已提交
181 182
                            # self.__gen_sql(select_claus, self.__join_condition(join_tblist, INNER=True), group_claus ),
                            self.__gen_sql(select_claus, self.__join_condition(join_tblist, INNER=True) ),
C
cpwu 已提交
183 184
                        )
                    )
C
cpwu 已提交
185
        return list(filter(None, sqls))
C
cpwu 已提交
186 187

    def __join_check(self,):
C
cpwu 已提交
188
        tdLog.printNoPrefix("==========current sql condition check , must return query ok==========")
C
cpwu 已提交
189 190
        for i in range(len(self.__sqls_list)):
            tdSql.query(self.__sqls_list[i])
C
cpwu 已提交
191 192
            # if i % 10 == 0 :
            #     tdLog.success(f"{i} sql is already executed success !")
C
cpwu 已提交
193 194

    def __join_check_old(self, tblist, checkrows, join_flag=True):
C
cpwu 已提交
195 196 197 198
        query_conditions = self.__query_condition(tblist[0])
        join_condition = self.__join_condition(tb_list=tblist) if join_flag else " "
        for condition in query_conditions:
            where_condition =  self.__where_condition(col=condition, tbname=tblist[0])
C
cpwu 已提交
199 200
            group_having = self.__group_condition(col=condition, having=f"{condition} is not null " )
            group_no_having= self.__group_condition(col=condition )
C
cpwu 已提交
201 202
            groups = ["", group_having, group_no_having]
            for group_condition in groups:
C
cpwu 已提交
203 204 205 206 207
                if where_condition:
                    sql = f" select {condition} from {tblist[0]},{tblist[1]} where {join_condition} and {where_condition} {group_condition} "
                else:
                    sql = f" select {condition} from {tblist[0]},{tblist[1]} where {join_condition}  {group_condition} "

C
cpwu 已提交
208 209
                if not join_flag :
                    tdSql.error(sql=sql)
C
cpwu 已提交
210
                    break
C
cpwu 已提交
211
                if len(tblist) == 2:
C
cpwu 已提交
212
                    if "ct1" in tblist or "nt1" in tblist:
C
cpwu 已提交
213
                        self.__join_current(sql, checkrows)
C
cpwu 已提交
214
                    elif where_condition or "not null" in group_condition:
C
cpwu 已提交
215
                        self.__join_current(sql, checkrows + 2 )
C
cpwu 已提交
216 217
                    elif group_condition:
                        self.__join_current(sql, checkrows + 3 )
C
cpwu 已提交
218 219
                    else:
                        self.__join_current(sql, checkrows + 5 )
C
cpwu 已提交
220
                if len(tblist) > 2 or len(tblist) < 1:
C
cpwu 已提交
221
                    tdSql.error(sql=sql)
C
cpwu 已提交
222

C
cpwu 已提交
223 224
    def __join_current(self, sql, checkrows):
        tdSql.query(sql=sql)
C
cpwu 已提交
225
        # tdSql.checkRows(checkrows)
C
cpwu 已提交
226

C
cpwu 已提交
227
    def __test_error(self):
C
cpwu 已提交
228
        # sourcery skip: extract-duplicate-method, move-assign-in-block
C
cpwu 已提交
229
        tdLog.printNoPrefix("==========err sql condition check , must return error==========")
C
cpwu 已提交
230
        err_list_1 = ["ct1","ct2", "ct4"]
C
cpwu 已提交
231 232 233 234
        err_list_2 = ["ct1","ct2", "nt1"]
        err_list_3 = ["ct1","ct4", "nt1"]
        err_list_4 = ["ct2","ct4", "nt1"]
        err_list_5 = ["ct1", "ct2","ct4", "nt1"]
C
cpwu 已提交
235
        self.__join_check_old(err_list_1, -1)
C
cpwu 已提交
236
        tdLog.printNoPrefix(f"==========err sql condition check in {err_list_1} over==========")
C
cpwu 已提交
237
        self.__join_check_old(err_list_2, -1)
C
cpwu 已提交
238
        tdLog.printNoPrefix(f"==========err sql condition check in {err_list_2} over==========")
C
cpwu 已提交
239
        self.__join_check_old(err_list_3, -1)
C
cpwu 已提交
240
        tdLog.printNoPrefix(f"==========err sql condition check in {err_list_3} over==========")
C
cpwu 已提交
241
        self.__join_check_old(err_list_4, -1)
C
cpwu 已提交
242
        tdLog.printNoPrefix(f"==========err sql condition check in {err_list_4} over==========")
C
cpwu 已提交
243
        self.__join_check_old(err_list_5, -1)
C
cpwu 已提交
244
        tdLog.printNoPrefix(f"==========err sql condition check in {err_list_5} over==========")
C
cpwu 已提交
245
        self.__join_check_old(["ct2", "ct4"], -1, join_flag=False)
C
cpwu 已提交
246 247 248 249 250 251 252 253 254 255
        tdLog.printNoPrefix("==========err sql condition check in has no join condition over==========")

        tdSql.error( f"select c1, c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{PRIMARY_COL}" )
        tdSql.error( f"select ct2.c1, ct2.c2 from ct2, ct4 where ct2.{INT_COL}=ct4.{INT_COL}" )
        tdSql.error( f"select ct2.c1, ct2.c2 from ct2, ct4 where ct2.{TS_COL}=ct4.{TS_COL}" )
        tdSql.error( f"select ct2.c1, ct2.c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{TS_COL}" )
        tdSql.error( f"select ct2.c1, ct1.c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{PRIMARY_COL}" )
        tdSql.error( f"select ct2.c1, ct4.c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{PRIMARY_COL} and c1 is not null " )
        tdSql.error( f"select ct2.c1, ct4.c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{PRIMARY_COL} and ct1.c1 is not null " )

C
cpwu 已提交
256

C
cpwu 已提交
257
        tbname = ["ct1", "ct2", "ct4", "nt1"]
C
cpwu 已提交
258

C
cpwu 已提交
259 260 261 262
        # for tb in tbname:
        #     for errsql in self.__join_err_check(tb):
        #         tdSql.error(sql=errsql)
        #     tdLog.printNoPrefix(f"==========err sql condition check in {tb} over==========")
C
cpwu 已提交
263 264 265


    def all_test(self):
C
cpwu 已提交
266
        self.__join_check()
C
cpwu 已提交
267 268 269
        self.__test_error()


C
cpwu 已提交
270 271 272
    def __create_tb(self, stb=STBNAME, ctb_num=20, ntbnum=1):
        tdLog.printNoPrefix("==========step: create table")
        create_stb_sql = f'''create table {stb}(
C
cpwu 已提交
273
                ts timestamp, {INT_COL} int, {BINT_COL} bigint, {SINT_COL} smallint, {TINT_COL} tinyint,
C
cpwu 已提交
274 275 276 277 278
                {FLOAT_COL} float, {DOUBLE_COL} double, {BOOL_COL} bool,
                {BINARY_COL} binary(16), {NCHAR_COL} nchar(32), {TS_COL} timestamp,
                {TINT_UN_COL} tinyint unsigned, {SINT_UN_COL} smallint unsigned,
                {INT_UN_COL} int unsigned, {BINT_UN_COL} bigint unsigned
            ) tags ({INT_TAG} int)
C
cpwu 已提交
279
            '''
C
cpwu 已提交
280 281 282 283 284 285 286 287 288 289
        for i in range(ntbnum):

            create_ntb_sql = f'''create table nt{i+1}(
                    ts timestamp, {INT_COL} int, {BINT_COL} bigint, {SINT_COL} smallint, {TINT_COL} tinyint,
                    {FLOAT_COL} float, {DOUBLE_COL} double, {BOOL_COL} bool,
                    {BINARY_COL} binary(16), {NCHAR_COL} nchar(32), {TS_COL} timestamp,
                    {TINT_UN_COL} tinyint unsigned, {SINT_UN_COL} smallint unsigned,
                    {INT_UN_COL} int unsigned, {BINT_UN_COL} bigint unsigned
                )
                '''
C
cpwu 已提交
290 291 292
        tdSql.execute(create_stb_sql)
        tdSql.execute(create_ntb_sql)

C
cpwu 已提交
293 294 295 296 297
        for i in range(ctb_num):
            tdSql.execute(f'create table ct{i+1} using {stb} tags ( {i+1} )')

    def __data_set(self, rows):
        data_set = DataSet()
C
cpwu 已提交
298 299

        for i in range(rows):
C
cpwu 已提交
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
            data_set.ts_data.append(NOW + 1 * (rows - i))
            data_set.int_data.append(rows - i)
            data_set.bint_data.append(11111 * (rows - i))
            data_set.sint_data.append(111 * (rows - i) % 32767)
            data_set.tint_data.append(11 * (rows - i) % 127)
            data_set.int_un_data.append(rows - i)
            data_set.bint_un_data.append(11111 * (rows - i))
            data_set.sint_un_data.append(111 * (rows - i) % 32767)
            data_set.tint_un_data.append(11 * (rows - i) % 127)
            data_set.float_data.append(1.11 * (rows - i))
            data_set.double_data.append(1100.0011 * (rows - i))
            data_set.bool_data.append((rows - i) % 2)
            data_set.binary_data.append(f'binary{(rows - i)}')
            data_set.nchar_data.append(f'nchar_测试_{(rows - i)}')

        return data_set

    def __insert_data(self):
        tdLog.printNoPrefix("==========step: start inser data into tables now.....")
        data = self.__data_set(rows=self.rows)

        # now_time = int(datetime.datetime.timestamp(datetime.datetime.now()) * 1000)
        null_data = '''null, null, null, null, null, null, null, null, null, null, null, null, null, null'''
        zero_data = "0, 0, 0, 0, 0, 0, 0, 'binary_0', 'nchar_0', 0, 0, 0, 0, 0"

        for i in range(self.rows):
            row_data = f'''
                {data.int_data[i]}, {data.bint_data[i]}, {data.sint_data[i]}, {data.tint_data[i]}, {data.float_data[i]}, {data.double_data[i]},
                {data.bool_data[i]}, '{data.binary_data[i]}', '{data.nchar_data[i]}', {data.ts_data[i]}, {data.tint_un_data[i]},
                {data.sint_un_data[i]}, {data.int_un_data[i]}, {data.bint_un_data[i]}
C
cpwu 已提交
330
            '''
C
cpwu 已提交
331 332 333 334
            neg_row_data = f'''
                {-1 * data.int_data[i]}, {-1 * data.bint_data[i]}, {-1 * data.sint_data[i]}, {-1 * data.tint_data[i]}, {-1 * data.float_data[i]}, {-1 * data.double_data[i]},
                {data.bool_data[i]}, '{data.binary_data[i]}', '{data.nchar_data[i]}', {data.ts_data[i]}, {1 * data.tint_un_data[i]},
                {1 * data.sint_un_data[i]}, {1 * data.int_un_data[i]}, {1 * data.bint_un_data[i]}
C
cpwu 已提交
335 336
            '''

C
cpwu 已提交
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
            tdSql.execute( f"insert into ct1 values ( {NOW - i * TIME_STEP}, {row_data} )" )
            tdSql.execute( f"insert into ct2 values ( {NOW - i * int(TIME_STEP * 0.6)}, {neg_row_data} )" )
            tdSql.execute( f"insert into ct4 values ( {NOW - i * int(TIME_STEP * 0.8) }, {row_data} )" )
            tdSql.execute( f"insert into {NTBNAME} values ( {NOW - i * int(TIME_STEP * 1.2)}, {row_data} )" )

        tdSql.execute( f"insert into ct2 values ( {NOW + int(TIME_STEP * 0.6)}, {null_data} )" )
        tdSql.execute( f"insert into ct2 values ( {NOW - (self.rows + 1) * int(TIME_STEP * 0.6)}, {null_data} )" )
        tdSql.execute( f"insert into ct2 values ( {NOW - self.rows * int(TIME_STEP * 0.29) }, {null_data} )" )

        tdSql.execute( f"insert into ct4 values ( {NOW + int(TIME_STEP * 0.8)}, {null_data} )" )
        tdSql.execute( f"insert into ct4 values ( {NOW - (self.rows + 1) * int(TIME_STEP * 0.8)}, {null_data} )" )
        tdSql.execute( f"insert into ct4 values ( {NOW - self.rows * int(TIME_STEP * 0.39)}, {null_data} )" )

        tdSql.execute( f"insert into {NTBNAME} values ( {NOW + int(TIME_STEP * 1.2)}, {null_data} )" )
        tdSql.execute( f"insert into {NTBNAME} values ( {NOW - (self.rows + 1) * int(TIME_STEP * 1.2)}, {null_data} )" )
        tdSql.execute( f"insert into {NTBNAME} values ( {NOW - self.rows * int(TIME_STEP * 0.59)}, {null_data} )" )
C
cpwu 已提交
353 354 355 356 357 358 359 360 361


    def run(self):
        tdSql.prepare()

        tdLog.printNoPrefix("==========step1:create table")
        self.__create_tb()

        tdLog.printNoPrefix("==========step2:insert data")
C
cpwu 已提交
362
        self.rows = 10
C
cpwu 已提交
363
        self.__insert_data()
C
cpwu 已提交
364 365

        tdLog.printNoPrefix("==========step3:all check")
C
cpwu 已提交
366 367
        tdSql.query("select count(*) from ct1")
        tdSql.checkData(0, 0, self.rows)
C
cpwu 已提交
368
        self.all_test()
C
cpwu 已提交
369

C
cpwu 已提交
370
        tdLog.printNoPrefix("==========step4:cross db check")
C
cpwu 已提交
371
        tdSql.execute("create database db1 duration 432000m")
C
cpwu 已提交
372 373
        tdSql.execute("use db1")
        self.__create_tb()
C
cpwu 已提交
374 375 376 377 378
        self.__insert_data()

        tdSql.query("select count(*) from ct1")
        tdSql.checkData(0, 0, self.rows)

C
cpwu 已提交
379
        self.all_test()
C
cpwu 已提交
380 381
        tdSql.query("select count(*) from ct1")
        tdSql.checkData(0, 0, self.rows)
C
cpwu 已提交
382

C
cpwu 已提交
383 384 385
        tdSql.execute("flush database db")
        # tdDnodes.stop(1)
        # tdDnodes.start(1)
C
cpwu 已提交
386

C
cpwu 已提交
387
        tdSql.execute("use db")
C
cpwu 已提交
388 389
        tdSql.query("select count(*) from ct1")
        tdSql.checkData(0, 0, self.rows)
C
cpwu 已提交
390

C
cpwu 已提交
391 392
        tdLog.printNoPrefix("==========step4:after wal, all check again ")
        self.all_test()
C
cpwu 已提交
393 394
        tdSql.query("select count(*) from ct1")
        tdSql.checkData(0, 0, self.rows)
C
cpwu 已提交
395 396 397 398 399 400 401

    def stop(self):
        tdSql.close()
        tdLog.success(f"{__file__} successfully executed")

tdCases.addLinux(__file__, TDTestCase())
tdCases.addWindows(__file__, TDTestCase())