操作符运算兼容

在将参数开关dolphin.b_compatibility_mode设置为on时,表示启用四则运算的MySQL兼容。相比于原始的openGauss,dolphin对于四则运算的修改主要为:

  1. 支持更多类型参与四则运算,具体如下:

    • 数字类型:tinyint(unsigned)、smallint(unsigned)、integer(unsigned)、bigint(unsigned)、float4、float8、decimal/numeric以及bit。
    • 字符串类型:char、varchar、binary、varbinary、tinyblob、blob、mediumblob、longblob、enum、set、json以及text(目前openGauss没有实际上的tinytext、mediumtext和longtext,因此不考虑)。
    • 时间日期类型:date、datetime、timestamp、time、year。
  2. 一些原操作符返回值兼容MySQL,具体的兼容规则如下:

    • 整型 X 整型:针对”+”、”-“、”*“这三个操作符,如果两个都是有符号的整型,则返回结果也是有符号的整型,否则返回无符号整型;针对”/“,其返回值为定点型(numeric类型)。
    • 整型 X 定点型:针对”+”、”-“、”*“、”/“四则运算,返回定点型。注:openGauss定点数未实现无符号,所以无符号整型参与运算返回的结果均为有符号的。
    • 整型 X 浮点型:针对”+”、”-“、”*“、”/“四则运算,返回浮点型。注:openGauss浮点数未实现无符号,所以无符号整型参与运算返回的结果均为有符号的。
    • 定点型 X 定点型:针对”+”、”-“、”*“、”/“四则运算,返回定点型。
    • 定点型 X 浮点型:针对”+”、”-“、”*“、”/“四则运算,返回浮点型。
    • 浮点型 X 浮点型:针对”+”、”-“、”*“、”/“四则运算,返回浮点型。

    基于上述规则,只需要运用字符串类型、时间类型等的类型转换规则,就可以推算出这些类型进行混合运算时的返回值,类型转换规则如下:

    • 字符串类型:在进行四则运算是统一转换为浮点类型
    • 时间日期类型:date固定转换为有符号整型,year固定转换为无符号整型;针对datetime、timestamp、time三个类型,如果没有指定typmod(表示毫秒和微秒)的话,就转换为有符号整型,否则会转换为一个定点数,其小数位数与指定的typmod相同。

示例:

测试用例:

  1. create database test_db dbcompatibility 'B';
  2. \c test_db
  3. set dolphin.b_compatibility_mode to on;
  4. -- 整型 X 整型
  5. select 1::int4 + 1::int4;
  6. select 1::int4 - 1::int4;
  7. select 1::int4 * 1::int4;
  8. select 1::int4 / 1::int4;
  9. -- 整型 X 整型(带无符号)
  10. select 1::int4 + 1::uint4;
  11. select 1::int4 - 1::uint4;
  12. select 1::int4 * 1::uint4;
  13. select 1::int4 / 1::uint4;
  14. -- 整型 X 定点型
  15. select 1::int4 + 1::numeric;
  16. select 1::int4 - 1::numeric;
  17. select 1::int4 * 1::numeric;
  18. select 1::int4 / 1::numeric;
  19. -- 整型 X 浮点型
  20. select 1::int4 + 1::float8;
  21. select 1::int4 - 1::float8;
  22. select 1::int4 * 1::float8;
  23. select 1::int4 / 1::float8;
  24. -- 定点型 X 浮点型
  25. select 1::numeric + 1::float8;
  26. select 1::numeric - 1::float8;
  27. select 1::numeric * 1::float8;
  28. select 1::numeric / 1::float8;
  29. -- 整型 X 字符串
  30. select 1::int4 + '1.23'::text;
  31. select 1::int4 - '1.23'::text;
  32. select 1::int4 * '1.23'::text;
  33. select 1::int4 / '1.23'::text;
  34. -- 整型 X 日期
  35. select 1::int4 + '2022-01-01'::date;
  36. select 1::int4 - '2022-01-01'::date;
  37. select 1::int4 * '2022-01-01'::date;
  38. select 1::int4 / '2022-01-01'::date;
  39. -- 整型 X 时间(不带微秒)
  40. select 1::int4 + '12:12:12'::time;
  41. select 1::int4 - '12:12:12'::time;
  42. select 1::int4 * '12:12:12'::time;
  43. select 1::int4 / '12:12:12'::time;
  44. -- 整型 X 时间(带微秒)
  45. select 1::int4 + '12:12:12.36'::time(3);
  46. select 1::int4 - '12:12:12.36'::time(3);
  47. select 1::int4 * '12:12:12.36'::time(3);
  48. select 1::int4 / '12:12:12.36'::time(3);

结果:

  1. openGauss=# create database test_db dbcompatibility 'B';
  2. CREATE DATABASE
  3. openGauss=# \c test_db
  4. test_db=# set dolphin.b_compatibility_mode to on;
  5. SET
  6. test_db=# -- 整型 X 整型
  7. test_db=# select 1::int4 + 1::int4;
  8. ?column?
  9. ----------
  10. 2
  11. (1 row)
  12. test_db=# select 1::int4 - 1::int4;
  13. ?column?
  14. ----------
  15. 0
  16. (1 row)
  17. test_db=# select 1::int4 * 1::int4;
  18. ?column?
  19. ----------
  20. 1
  21. (1 row)
  22. test_db=# select 1::int4 / 1::int4;
  23. ?column?
  24. ------------------------
  25. 1.00000000000000000000
  26. (1 row)
  27. test_db=# -- 整型 X 整型(带无符号)
  28. test_db=# select 1::int4 + 1::uint4;
  29. ?column?
  30. ----------
  31. 2
  32. (1 row)
  33. test_db=# select 1::int4 - 1::uint4;
  34. ?column?
  35. ----------
  36. 0
  37. (1 row)
  38. test_db=# select 1::int4 * 1::uint4;
  39. ?column?
  40. ----------
  41. 1
  42. (1 row)
  43. test_db=# select 1::int4 / 1::uint4;
  44. ?column?
  45. ------------------------
  46. 1.00000000000000000000
  47. (1 row)
  48. test_db=# -- 整型 X 定点型
  49. test_db=# select 1::int4 + 1::numeric;
  50. ?column?
  51. ----------
  52. 2
  53. (1 row)
  54. test_db=# select 1::int4 - 1::numeric;
  55. ?column?
  56. ----------
  57. 0
  58. (1 row)
  59. test_db=# select 1::int4 * 1::numeric;
  60. ?column?
  61. ----------
  62. 1
  63. (1 row)
  64. test_db=# select 1::int4 / 1::numeric;
  65. ?column?
  66. ------------------------
  67. 1.00000000000000000000
  68. (1 row)
  69. test_db=# -- 整型 X 浮点型
  70. test_db=# select 1::int4 + 1::float8;
  71. ?column?
  72. ----------
  73. 2
  74. (1 row)
  75. test_db=# select 1::int4 - 1::float8;
  76. ?column?
  77. ----------
  78. 0
  79. (1 row)
  80. test_db=# select 1::int4 * 1::float8;
  81. ?column?
  82. ----------
  83. 1
  84. (1 row)
  85. test_db=# select 1::int4 / 1::float8;
  86. ?column?
  87. ----------
  88. 1
  89. (1 row)
  90. test_db=# -- 定点型 X 浮点型
  91. test_db=# select 1::numeric + 1::float8;
  92. ?column?
  93. ----------
  94. 2
  95. (1 row)
  96. test_db=# select 1::numeric - 1::float8;
  97. ?column?
  98. ----------
  99. 0
  100. (1 row)
  101. test_db=# select 1::numeric * 1::float8;
  102. ?column?
  103. ----------
  104. 1
  105. (1 row)
  106. test_db=# select 1::numeric / 1::float8;
  107. ?column?
  108. ----------
  109. 1
  110. (1 row)
  111. test_db=# -- 整型 X 字符串
  112. test_db=# select 1::int4 + '1.23'::text;
  113. ?column?
  114. ----------
  115. 2.23
  116. (1 row)
  117. test_db=# select 1::int4 - '1.23'::text;
  118. ?column?
  119. ----------
  120. -0.23
  121. (1 row)
  122. test_db=# select 1::int4 * '1.23'::text;
  123. ?column?
  124. ----------
  125. 1.23
  126. (1 row)
  127. test_db=# select 1::int4 / '1.23'::text;
  128. ?column?
  129. -------------------
  130. 0.813008130081301
  131. (1 row)
  132. test_db=# -- 整型 X 日期
  133. test_db=# select 1::int4 + '2022-01-01'::date;
  134. ?column?
  135. ----------
  136. 20220102
  137. (1 row)
  138. test_db=# select 1::int4 - '2022-01-01'::date;
  139. ?column?
  140. -----------
  141. -20220100
  142. (1 row)
  143. test_db=# select 1::int4 * '2022-01-01'::date;
  144. ?column?
  145. ----------
  146. 20220101
  147. (1 row)
  148. test_db=# select 1::int4 / '2022-01-01'::date;
  149. ?column?
  150. ----------------------------
  151. 0.000000049455737139987580
  152. (1 row)
  153. test_db=# -- 整型 X 时间(不带微秒)
  154. test_db=# select 1::int4 + '12:12:12'::time;
  155. ?column?
  156. ----------
  157. 121213
  158. (1 row)
  159. test_db=# select 1::int4 - '12:12:12'::time;
  160. ?column?
  161. ----------
  162. -121211
  163. (1 row)
  164. test_db=# select 1::int4 * '12:12:12'::time;
  165. ?column?
  166. ----------
  167. 121212
  168. (1 row)
  169. test_db=# select 1::int4 / '12:12:12'::time;
  170. ?column?
  171. ----------------------------
  172. 0.000008250008250008250008
  173. (1 row)
  174. test_db=# -- 整型 X 时间(带微秒)
  175. test_db=# select 1::int4 + '12:12:12.36'::time(3);
  176. ?column?
  177. ---------------
  178. 121213.360000
  179. (1 row)
  180. test_db=# select 1::int4 - '12:12:12.36'::time(3);
  181. ?column?
  182. ----------------
  183. -121211.360000
  184. (1 row)
  185. test_db=# select 1::int4 * '12:12:12.36'::time(3);
  186. ?column?
  187. ---------------
  188. 121212.360000
  189. (1 row)
  190. test_db=# select 1::int4 / '12:12:12.36'::time(3);
  191. ?column?
  192. ----------------------------
  193. 0.000008249983747532017362
  194. (1 row)