Commit 9ecd3ed90dff1d7a2849f86b1d10cfb84be29c1e

Authored by YunaiV
1 parent 1a482667

fix(statistics): 兼容 PostgreSQL 统计查询

移植 #1307 的日期、空值、逻辑删除及排序兼容调整。
31 条实际 XML 映射在 MySQL 与 PostgreSQL 各执行 102 次,结果一致。

Refs #1307, #1308
yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/infra/ApiAccessLogStatisticsMapper.xml
... ... @@ -7,7 +7,7 @@
7 7 FROM infra_api_access_log
8 8 WHERE user_type = #{userType}
9 9 AND create_time BETWEEN #{beginTime} AND #{endTime}
10   - AND deleted = FALSE
  10 + AND deleted = 0
11 11 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
12 12 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
13 13 </if>
... ... @@ -19,7 +19,7 @@
19 19 WHERE user_id > 0
20 20 AND user_type = #{userType}
21 21 AND create_time BETWEEN #{beginTime} AND #{endTime}
22   - AND deleted = FALSE
  22 + AND deleted = 0
23 23 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
24 24 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
25 25 </if>
... ...
yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/member/MemberStatisticsMapper.xml
... ... @@ -6,7 +6,7 @@
6 6 resultType="cn.iocoder.yudao.module.statistics.service.member.bo.MemberAreaStatisticsRespBO">
7 7 SELECT area_id, COUNT(1) AS userCount
8 8 FROM member_user
9   - WHERE deleted = FALSE
  9 + WHERE deleted = 0
10 10 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
11 11 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
12 12 </if>
... ... @@ -17,7 +17,7 @@
17 17 resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSexStatisticsRespVO">
18 18 SELECT sex, COUNT(1) AS userCount
19 19 FROM member_user
20   - WHERE deleted = FALSE
  20 + WHERE deleted = 0
21 21 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
22 22 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
23 23 </if>
... ... @@ -28,7 +28,7 @@
28 28 resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberTerminalStatisticsRespVO">
29 29 SELECT register_terminal as terminal, COUNT(1) AS userCount
30 30 FROM member_user
31   - WHERE deleted = FALSE
  31 + WHERE deleted = 0
32 32 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
33 33 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
34 34 </if>
... ... @@ -38,7 +38,7 @@
38 38 <select id="selectUserCount" resultType="java.lang.Integer">
39 39 SELECT COUNT(1)
40 40 FROM member_user
41   - WHERE deleted = FALSE
  41 + WHERE deleted = 0
42 42 <if test="beginTime != null">
43 43 AND create_time >= #{beginTime}
44 44 </if>
... ... @@ -52,15 +52,16 @@
52 52  
53 53 <select id="selectListByCreateTimeBetween"
54 54 resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberRegisterCountRespVO">
55   - SELECT DATE_FORMAT(create_time, '%Y-%m-%d') AS date,
  55 + SELECT CAST(create_time AS DATE) AS date,
56 56 count(1) AS count
57 57 FROM member_user
58 58 WHERE create_time BETWEEN #{beginTime} AND #{endTime}
59   - AND deleted = FALSE
  59 + AND deleted = 0
60 60 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
61 61 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
62 62 </if>
63 63 GROUP BY date
  64 + ORDER BY date
64 65 </select>
65 66  
66 67 </mapper>
... ...
yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/pay/PayWalletStatisticsMapper.xml
... ... @@ -9,7 +9,7 @@
9 9 FROM pay_wallet_recharge
10 10 WHERE pay_status = #{payStatus}
11 11 AND pay_time BETWEEN #{beginTime} AND #{endTime}
12   - AND deleted = FALSE
  12 + AND deleted = 0
13 13 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
14 14 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
15 15 </if>
... ... @@ -22,7 +22,7 @@
22 22 FROM pay_wallet_recharge
23 23 WHERE refund_status = #{refundStatus}
24 24 AND refund_time BETWEEN #{beginTime} AND #{endTime}
25   - AND deleted = FALSE
  25 + AND deleted = 0
26 26 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
27 27 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
28 28 </if>
... ... @@ -33,7 +33,7 @@
33 33 FROM pay_wallet_transaction
34 34 WHERE biz_type = #{bizType}
35 35 AND create_time BETWEEN #{beginTime} AND #{endTime}
36   - AND deleted = FALSE
  36 + AND deleted = 0
37 37 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
38 38 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
39 39 </if>
... ... @@ -51,17 +51,17 @@
51 51 <if test="endTime != null">
52 52 AND pay_time &lt;= #{endTime}
53 53 </if>
54   - AND deleted = FALSE
  54 + AND deleted = 0
55 55 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
56 56 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
57 57 </if>
58 58 </select>
59 59  
60 60 <select id="selectRechargePriceSummary" resultType="java.lang.Integer">
61   - SELECT IFNULL(SUM(pay_price), 0)
  61 + SELECT COALESCE(SUM(pay_price), 0)
62 62 FROM pay_wallet_recharge
63 63 WHERE pay_status = #{payStatus}
64   - AND deleted = FALSE
  64 + AND deleted = 0
65 65 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
66 66 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
67 67 </if>
... ...
yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/product/ProductStatisticsMapper.xml
... ... @@ -42,7 +42,7 @@
42 42 </if>
43 43 ) AS cart_count
44 44 -- 下单件数
45   - , (SELECT IFNULL(SUM(count), 0)
  45 + , (SELECT COALESCE(SUM(count), 0)
46 46 FROM trade_order_item
47 47 WHERE spu_id = spu.id
48 48 AND create_time BETWEEN #{beginTime} AND #{endTime}
... ... @@ -51,7 +51,7 @@
51 51 </if>
52 52 ) AS order_count
53 53 -- 支付件数
54   - , (SELECT IFNULL(SUM(item.count), 0)
  54 + , (SELECT COALESCE(SUM(item.count), 0)
55 55 FROM trade_order_item item
56 56 JOIN trade_order o ON item.order_id = o.id
57 57 WHERE spu_id = spu.id
... ... @@ -63,7 +63,7 @@
63 63 </if>
64 64 ) AS order_pay_count
65 65 -- 支付金额
66   - , (SELECT IFNULL(SUM(item.pay_price), 0)
  66 + , (SELECT COALESCE(SUM(item.pay_price), 0)
67 67 FROM trade_order_item item
68 68 JOIN trade_order o ON item.order_id = o.id
69 69 WHERE spu_id = spu.id
... ... @@ -75,7 +75,7 @@
75 75 </if>
76 76 ) AS order_pay_price
77 77 -- 退款件数
78   - , (SELECT IFNULL(SUM(count), 0)
  78 + , (SELECT COALESCE(SUM(count), 0)
79 79 FROM trade_after_sale
80 80 WHERE spu_id = spu.id
81 81 AND refund_time IS NOT NULL
... ... @@ -85,7 +85,7 @@
85 85 </if>
86 86 ) AS after_sale_count
87 87 -- 退款金额
88   - , (SELECT IFNULL(SUM(refund_price), 0)
  88 + , (SELECT COALESCE(SUM(refund_price), 0)
89 89 FROM trade_after_sale
90 90 WHERE spu_id = spu.id
91 91 AND refund_time IS NOT NULL
... ... @@ -95,7 +95,7 @@
95 95 </if>
96 96 ) AS after_sale_refund_price
97 97 FROM product_spu spu
98   - WHERE spu.deleted = FALSE
  98 + WHERE spu.deleted = 0
99 99 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
100 100 AND spu.tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
101 101 </if>
... ...
yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/AfterSaleStatisticsMapper.xml
... ... @@ -8,7 +8,7 @@
8 8 SUM(refund_price) AS afterSaleRefundPrice
9 9 FROM trade_after_sale
10 10 WHERE refund_time BETWEEN #{beginTime} AND #{endTime}
11   - AND deleted = FALSE
  11 + AND deleted = 0
12 12 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
13 13 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
14 14 </if>
... ... @@ -18,7 +18,7 @@
18 18 SELECT COUNT(1)
19 19 FROM trade_after_sale
20 20 WHERE status = #{status}
21   - AND deleted = FALSE
  21 + AND deleted = 0
22 22 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
23 23 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
24 24 </if>
... ...
yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/BrokerageStatisticsMapper.xml
... ... @@ -8,7 +8,7 @@
8 8 WHERE biz_type = #{bizType}
9 9 AND status = #{status}
10 10 AND unfreeze_time BETWEEN #{beginTime} AND #{endTime}
11   - AND deleted = FALSE
  11 + AND deleted = 0
12 12 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
13 13 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
14 14 </if>
... ... @@ -18,7 +18,7 @@
18 18 SELECT COUNT(1)
19 19 FROM trade_brokerage_withdraw
20 20 WHERE status = #{status}
21   - AND deleted = FALSE
  21 + AND deleted = 0
22 22 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
23 23 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
24 24 </if>
... ...
yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml
... ... @@ -16,7 +16,7 @@
16 16 FROM trade_order AS s
17 17 WHERE s.receiver_area_id = m.receiver_area_id
18 18 AND s.pay_status = TRUE
19   - AND s.deleted = FALSE
  19 + AND s.deleted = 0
20 20 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
21 21 AND s.tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
22 22 </if>
... ... @@ -25,13 +25,13 @@
25 25 FROM trade_order AS s
26 26 WHERE s.receiver_area_id = m.receiver_area_id
27 27 AND s.pay_status = TRUE
28   - AND s.deleted = FALSE
  28 + AND s.deleted = 0
29 29 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
30 30 AND s.tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
31 31 </if>
32 32 ) AS orderPayPrice
33 33 FROM trade_order m
34   - WHERE deleted = FALSE
  34 + WHERE deleted = 0
35 35 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
36 36 AND m.tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
37 37 </if>
... ... @@ -41,7 +41,7 @@
41 41 <select id="selectUserCountByCreateTimeBetween" resultType="java.lang.Integer">
42 42 SELECT COUNT(DISTINCT (user_id))
43 43 FROM trade_order
44   - WHERE deleted = FALSE
  44 + WHERE deleted = 0
45 45 AND create_time BETWEEN #{beginTime} AND #{endTime}
46 46 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
47 47 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
... ... @@ -53,7 +53,7 @@
53 53 FROM trade_order
54 54 WHERE pay_time BETWEEN #{beginTime} AND #{endTime}
55 55 AND pay_status = TRUE
56   - AND deleted = FALSE
  56 + AND deleted = 0
57 57 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
58 58 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
59 59 </if>
... ... @@ -63,7 +63,7 @@
63 63 SELECT COUNT(1)
64 64 FROM trade_order
65 65 WHERE create_time BETWEEN #{beginTime} AND #{endTime}
66   - AND deleted = FALSE
  66 + AND deleted = 0
67 67 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
68 68 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
69 69 </if>
... ... @@ -74,7 +74,7 @@
74 74 FROM trade_order
75 75 WHERE pay_status = TRUE
76 76 AND create_time BETWEEN #{beginTime} AND #{endTime}
77   - AND deleted = FALSE
  77 + AND deleted = 0
78 78 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
79 79 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
80 80 </if>
... ... @@ -84,7 +84,7 @@
84 84 SELECT SUM(pay_price)
85 85 FROM trade_order AS s
86 86 WHERE s.pay_status = TRUE
87   - AND deleted = FALSE
  87 + AND deleted = 0
88 88 AND create_time BETWEEN #{beginTime} AND #{endTime}
89 89 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
90 90 AND s.tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
... ... @@ -93,32 +93,35 @@
93 93  
94 94 <select id="selectListByPayTimeBetweenAndGroupByDay"
95 95 resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderTrendRespVO">
96   - SELECT DATE_FORMAT(pay_time, '%Y-%m-%d') AS date,
  96 + SELECT CAST(pay_time AS DATE) AS date,
97 97 COUNT(1) AS orderPayCount,
98 98 SUM(pay_price) AS orderPayPrice
99 99 FROM trade_order
100 100 WHERE pay_status = TRUE
101 101 AND create_time BETWEEN #{beginTime} AND #{endTime}
102   - AND deleted = FALSE
  102 + AND deleted = 0
103 103 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
104 104 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
105 105 </if>
106 106 GROUP BY date
  107 + ORDER BY date
107 108 </select>
108 109  
109 110 <select id="selectListByPayTimeBetweenAndGroupByMonth"
110 111 resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderTrendRespVO">
111   - SELECT DATE_FORMAT(pay_time, '%Y-%m') AS date,
  112 + SELECT CONCAT(EXTRACT(YEAR FROM pay_time), '-',
  113 + LPAD(CONCAT(EXTRACT(MONTH FROM pay_time)), 2, '0')) AS date,
112 114 COUNT(1) AS order_pay_count,
113 115 SUM(pay_price) AS order_pay_price
114 116 FROM trade_order
115 117 WHERE pay_status = TRUE
116 118 AND create_time BETWEEN #{beginTime} AND #{endTime}
117   - AND deleted = FALSE
  119 + AND deleted = 0
118 120 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
119 121 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
120 122 </if>
121 123 GROUP BY date
  124 + ORDER BY date
122 125 </select>
123 126  
124 127 <select id="selectCountByStatusAndDeliveryType" resultType="java.lang.Long">
... ... @@ -126,7 +129,7 @@
126 129 FROM trade_order
127 130 WHERE status = #{status}
128 131 ANd delivery_type = #{deliveryType}
129   - AND deleted = FALSE
  132 + AND deleted = 0
130 133 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
131 134 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
132 135 </if>
... ... @@ -134,12 +137,12 @@
134 137  
135 138 <select id="selectPaySummaryByPayStatusAndPayTimeBetween"
136 139 resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeOrderSummaryRespVO">
137   - SELECT IFNULL(SUM(pay_price), 0) AS order_pay_price,
  140 + SELECT COALESCE(SUM(pay_price), 0) AS order_pay_price,
138 141 COUNT(1) AS order_pay_count
139 142 FROM trade_order
140 143 WHERE pay_status = #{payStatus}
141 144 AND pay_time BETWEEN #{beginTime} AND #{endTime}
142   - AND deleted = FALSE
  145 + AND deleted = 0
143 146 <if test="@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId() != null">
144 147 AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()}
145 148 </if>
... ...
yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeStatisticsMapper.xml
... ... @@ -4,11 +4,11 @@
4 4  
5 5 <select id="selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween"
6 6 resultType="cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO">
7   - SELECT IFNULL(SUM(order_create_count), 0) AS count,
8   - IFNULL(SUM(order_pay_price), 0) AS summary
  7 + SELECT COALESCE(SUM(order_create_count), 0) AS count,
  8 + COALESCE(SUM(order_pay_price), 0) AS summary
9 9 FROM trade_statistics
10 10 WHERE time BETWEEN #{beginTime} AND #{endTime}
11   - AND deleted = FALSE
  11 + AND deleted = 0
12 12 </select>
13 13  
14 14 <select id="selectVoByTimeBetween"
... ... @@ -25,14 +25,14 @@
25 25 SUM(after_sale_refund_price) AS afterSaleRefundPrice
26 26 FROM trade_statistics
27 27 WHERE time BETWEEN #{beginTime} AND #{endTime}
28   - AND deleted = FALSE
  28 + AND deleted = 0
29 29 </select>
30 30  
31 31 <select id="selectExpensePriceByTimeBetween" resultType="java.lang.Integer">
32 32 SELECT -- 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额
33 33 SUM(wallet_pay_price + brokerage_settlement_price + after_sale_refund_price) AS expensePrice
34 34 FROM trade_statistics
35   - WHERE deleted = FALSE
  35 + WHERE deleted = 0
36 36 <if test="beginTime != null">
37 37 AND time >= #{beginTime}
38 38 </if>
... ...
yudao-module-mall/yudao-module-trade/src/main/resources/mapper/brokerage/BrokerageUserMapper.xml
... ... @@ -17,14 +17,14 @@
17 17 resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO">
18 18 SELECT bu.id, bu.bind_user_time AS brokerageTime,
19 19 (SELECT SUM(price) FROM trade_brokerage_record r
20   - WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokeragePrice,
  20 + WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = 0) AS brokeragePrice,
21 21 (SELECT COUNT(1) FROM trade_brokerage_record r
22   - WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokerageOrderCount,
  22 + WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = 0) AS brokerageOrderCount,
23 23 (SELECT COUNT(1) FROM trade_brokerage_user c
24   - WHERE c.bind_user_id = bu.id AND c.deleted = FALSE) AS brokerageUserCount
  24 + WHERE c.bind_user_id = bu.id AND c.deleted = 0) AS brokerageUserCount
25 25 FROM trade_brokerage_user AS bu
26 26 <where>
27   - bu.deleted = false
  27 + bu.deleted = 0
28 28 <if test="ids != null and ids.size() > 0">
29 29 and bu.id in
30 30 <foreach collection="ids" open="(" item="id" separator="," close=")">
... ...