├── docker-compose.yml ├── src ├── main │ ├── java │ │ └── org │ │ │ └── mvnsearch │ │ │ └── h2 │ │ │ ├── H2FunctionsLoader.java │ │ │ └── mysql │ │ │ ├── MiscFunctions.java │ │ │ ├── MathFunctions.java │ │ │ ├── EncryptionFunctions.java │ │ │ ├── StringFunctions.java │ │ │ └── DateTimeFunctions.java │ └── resources │ │ └── db │ │ └── migration │ │ └── h2 │ │ └── V0__functions.sql └── test │ ├── java │ └── org │ │ └── mvnsearch │ │ └── h2 │ │ └── mysql │ │ └── FunctionsTest.java │ └── resources │ └── testing.sql ├── .gitignore ├── pom.xml ├── LICENSE └── README.md /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | mysql: 4 | image: mysql:5.6.37 5 | ports: 6 | - "3306:3306" 7 | environment: 8 | MYSQL_ROOT_PASSWORD: 123456 9 | MYSQL_DATABASE: h2 10 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/h2/H2FunctionsLoader.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.h2; 2 | 3 | import org.h2.tools.RunScript; 4 | import org.h2.util.IOUtils; 5 | 6 | import javax.sql.DataSource; 7 | import java.sql.Connection; 8 | 9 | /** 10 | * H2 functions loader 11 | * 12 | * @author linux_china 13 | */ 14 | public class H2FunctionsLoader { 15 | 16 | public static void loadMysqlFunctions(DataSource dataSource) { 17 | try { 18 | Connection conn = dataSource.getConnection(); 19 | RunScript.execute(conn, IOUtils.getReader(H2FunctionsLoader.class.getResourceAsStream("/db/migration/h2/V0__functions.sql"))); 20 | conn.close(); 21 | } catch (Exception ignore) { 22 | 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/h2/mysql/MiscFunctions.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.h2.mysql; 2 | 3 | import java.text.NumberFormat; 4 | import java.util.Locale; 5 | 6 | /** 7 | * misc functions 8 | * 9 | * @author linux_china 10 | */ 11 | public class MiscFunctions { 12 | 13 | public static String version() { 14 | return "5.6.25"; 15 | } 16 | 17 | public static String format(Double value, Integer p) { 18 | NumberFormat format = NumberFormat.getInstance(); 19 | format.setMaximumFractionDigits(p); 20 | return format.format(value); 21 | } 22 | 23 | public static String format(Double value, Integer p, String locale) { 24 | NumberFormat format = NumberFormat.getInstance(new Locale(locale)); 25 | format.setMaximumFractionDigits(p); 26 | return format.format(value); 27 | } 28 | 29 | public static Integer connectId() { 30 | return 1; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/org/mvnsearch/h2/mysql/FunctionsTest.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.h2.mysql; 2 | 3 | import org.h2.jdbcx.JdbcDataSource; 4 | import org.h2.tools.RunScript; 5 | import org.h2.util.IOUtils; 6 | import org.h2.util.StringUtils; 7 | import org.junit.Test; 8 | 9 | import java.io.Reader; 10 | import java.sql.Connection; 11 | import java.sql.ResultSet; 12 | import java.sql.Statement; 13 | 14 | /** 15 | * functions test 16 | * 17 | * @author linux_china 18 | */ 19 | public class FunctionsTest { 20 | 21 | @Test 22 | public void testExecuteQuery() throws Exception { 23 | JdbcDataSource dataSource = dataSource(); 24 | Connection connection = dataSource.getConnection(); 25 | Statement statement = connection.createStatement(); 26 | Reader reader = IOUtils.getReader(this.getClass().getResourceAsStream("/testing.sql")); 27 | String content = IOUtils.readStringAndClose(reader, -1); 28 | String[] sentences = StringUtils.arraySplit(content, ';', true); 29 | for (String sentence : sentences) { 30 | if (sentence != null && !sentence.isEmpty() && !sentence.startsWith("--")) { 31 | ResultSet resultSet = statement.executeQuery(sentence); 32 | resultSet.next(); 33 | System.out.println("Succeeded: " + sentence + " = " + resultSet.getString(1)); 34 | resultSet.close(); 35 | } 36 | } 37 | statement.close(); 38 | } 39 | 40 | private JdbcDataSource dataSource() throws Exception { 41 | JdbcDataSource dataSource = new JdbcDataSource(); 42 | dataSource.setURL("jdbc:h2:mem:public"); 43 | dataSource.setUser("sa"); 44 | RunScript.execute(dataSource.getConnection(), IOUtils.getReader(this.getClass().getResourceAsStream("/db/migration/h2/V0__functions.sql"))); 45 | return dataSource; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/h2/mysql/MathFunctions.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.h2.mysql; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * math functions 7 | * 8 | * @author linux_china 9 | */ 10 | public class MathFunctions { 11 | 12 | private static char[] array = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); 13 | private static String numStr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 14 | 15 | public static Double pow(Double a, Double b) { 16 | return Math.pow(a, b); 17 | } 18 | 19 | public static String conv(String text, Integer originBase, Integer targetBase) { 20 | String sign = ""; 21 | if (text.startsWith("-")) { 22 | sign = "-"; 23 | } 24 | long number = N_to_10(text.replace("-", ""), originBase); 25 | return sign + _10_to_N(number, targetBase); 26 | } 27 | 28 | public static String _10_to_N(long number, int N) { 29 | long rest = number; 30 | Stack stack = new Stack<>(); 31 | StringBuilder result = new StringBuilder(0); 32 | while (rest != 0) { 33 | stack.add(array[new Long((rest % N)).intValue()]); 34 | rest = rest / N; 35 | } 36 | for (; !stack.isEmpty(); ) { 37 | result.append(stack.pop()); 38 | } 39 | return result.length() == 0 ? "0" : result.toString(); 40 | } 41 | 42 | public static long N_to_10(String number, int N) { 43 | char ch[] = number.toCharArray(); 44 | int len = ch.length; 45 | long result = 0; 46 | if (N == 10) { 47 | return Long.parseLong(number); 48 | } 49 | long base = 1; 50 | for (int i = len - 1; i >= 0; i--) { 51 | int index = numStr.indexOf(ch[i]); 52 | result += index * base; 53 | base *= N; 54 | } 55 | return result; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | # User-specific stuff: 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/dictionaries 10 | 11 | # Sensitive or high-churn files: 12 | .idea/**/dataSources/ 13 | .idea/**/dataSources.ids 14 | .idea/**/dataSources.xml 15 | .idea/**/dataSources.local.xml 16 | .idea/**/sqlDataSources.xml 17 | .idea/**/dynamic.xml 18 | .idea/**/uiDesigner.xml 19 | 20 | # Gradle: 21 | .idea/**/gradle.xml 22 | .idea/**/libraries 23 | 24 | # CMake 25 | cmake-build-debug/ 26 | 27 | # Mongo Explorer plugin: 28 | .idea/**/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.iws 32 | *.iml 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Cursive Clojure plugin 46 | .idea/replstate.xml 47 | 48 | # Crashlytics plugin (for Android Studio and IntelliJ) 49 | com_crashlytics_export_strings.xml 50 | crashlytics.properties 51 | crashlytics-build.properties 52 | fabric.properties 53 | ### Maven template 54 | target/ 55 | pom.xml.tag 56 | pom.xml.releaseBackup 57 | pom.xml.versionsBackup 58 | pom.xml.next 59 | release.properties 60 | dependency-reduced-pom.xml 61 | buildNumber.properties 62 | .mvn/timing.properties 63 | 64 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 65 | !/.mvn/wrapper/maven-wrapper.jar 66 | ### Java template 67 | # Compiled class file 68 | *.class 69 | 70 | # Log file 71 | *.log 72 | 73 | # BlueJ files 74 | *.ctxt 75 | 76 | # Mobile Tools for Java (J2ME) 77 | .mtj.tmp/ 78 | 79 | # Package Files # 80 | *.jar 81 | *.war 82 | *.ear 83 | *.zip 84 | *.tar.gz 85 | *.rar 86 | 87 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 88 | hs_err_pid* 89 | 90 | -------------------------------------------------------------------------------- /src/test/resources/testing.sql: -------------------------------------------------------------------------------- 1 | SELECT UNIX_TIMESTAMP(); 2 | SELECT UNIX_TIMESTAMP('2005-03-27'); 3 | SELECT UNIX_TIMESTAMP('2005-03-27 03:00:00'); 4 | SELECT FROM_UNIXTIME(1111885200); 5 | SELECT version(); 6 | SELECT md5('abcd'); 7 | SELECT concat('*', sha1(unhex(sha1('123456')))); 8 | SELECT PASSWORD('123456'); 9 | SELECT TO_BASE64('abc'); 10 | SELECT FROM_BASE64(TO_BASE64('abc')); 11 | SELECT FORMAT(12332.123456, 4); 12 | SELECT FORMAT(12332.123456, 0); 13 | SELECT FORMAT(12332.123456, 2, 'de_DE'); 14 | select CURDATE(); 15 | select CURTIME(); 16 | select CEIL(1.23); 17 | SELECT now(); 18 | SELECT date(now()) as date1; 19 | select day(now()); 20 | select dayname(now()); 21 | select DAYOFMONTH(now()); 22 | SELECT POW(2, 2); 23 | select UUID(); 24 | select UTC_TIMESTAMP(); 25 | select UTC_DATE(); 26 | select UTC_TIME(); 27 | select UUID_SHORT(); 28 | SELECT FROM_DAYS(730669); 29 | SELECT TO_DAYS('2008-10-07'); 30 | SELECT TO_SECONDS('2009-11-29'); 31 | SELECT TIME_TO_SEC('22:23:00'); 32 | SELECT date('2003-12-31 01:02:03'); 33 | SELECT TIME('2003-12-31 01:02:03'); 34 | SELECT SUBSTR('Quadratically', 5); 35 | SELECT MINUTE('2008-02-03 10:05:03'); 36 | SELECT BIT_LENGTH('text'); 37 | SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y'); 38 | SELECT TIME_FORMAT('10:10:10', '%H %k %h %I %l'); 39 | SELECT FIND_IN_SET('b', 'a,b,c,d'); 40 | SELECT INSERT('Quadratic', 3, 4, 'What'); 41 | SELECT IS_IPV4('10.0.5.9'); 42 | select IS_IPV4('10.0.5.256'); 43 | select IS_IPV6('::1'); 44 | SELECT IS_UUID('6ccd780c-baba-1026-9564-5b8c6560db'); 45 | SELECT LEAST(2, 0); 46 | SELECT LCASE('foobarBar'); 47 | SELECT LN(2); 48 | SELECT LAST_DAY('2003-02-05'); 49 | select LOCALTIME(); 50 | select LOCALTIMESTAMP(); 51 | SELECT MAKEDATE(2011, 31); 52 | SELECT MAKETIME(12, 15, 30); 53 | SELECT REVERSE('abc'); 54 | SELECT SEC_TO_TIME(2378); 55 | select SLEEP(2); 56 | SELECT STR_TO_DATE('01,5,2013', '%d,%m,%Y'); 57 | SELECT STR_TO_DATE('15:35:00', '%H:%i:%s'); 58 | SELECT SUBDATE('2008-01-02 12:00:00', 31); 59 | SELECT ADDDATE('2008-01-02', 31); 60 | SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002'); 61 | SELECT SUBTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002'); 62 | SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2); 63 | SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2); 64 | SELECT STRCMP('text', 'text2'); 65 | select current_user(); 66 | select connection_id(); 67 | select session_user(); 68 | select system_user(); 69 | SELECT CURRENT_ROLE(); 70 | SELECT YEARWEEK('1987-01-01'); 71 | SELECT week('1987-01-01'); 72 | SELECT WEEKOFYEAR('2008-02-20'); 73 | SELECT WEEKDAY('2018-5-17'); 74 | SELECT WEEKDAY('2007-11-06'); 75 | SELECT MICROSECOND('12:00:00.123456'); 76 | SELECT CRC32('MySQL'); 77 | SELECT CHARSET('abc'); 78 | SELECT CONV('a',16,2); 79 | SELECT CONV('-17',10,-18); 80 | SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET'); 81 | SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00'); 82 | select CREATE_DIGEST('SHA512', 'The quick brown fox'); 83 | SELECT FIELD('Bb', 'Aa', 'Bb', 'Cc', 'Dd', 'Ff'); 84 | SELECT mid('Quadratically',5); 85 | SELECT mid('Sakila', -5, 3); 86 | SELECT ORD('2'); 87 | SELECT PERIOD_ADD(200801,2); 88 | SELECT PERIOD_DIFF(200802,200703); 89 | SELECT TIMEDIFF('2008-12-31 23:59:59.00', '2008-12-31 22:58:58.00'); 90 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/h2/mysql/EncryptionFunctions.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.h2.mysql; 2 | 3 | import org.apache.commons.codec.binary.Base64; 4 | import org.apache.commons.codec.binary.Hex; 5 | import org.apache.commons.codec.digest.DigestUtils; 6 | import org.apache.commons.lang3.RandomUtils; 7 | 8 | import javax.crypto.Cipher; 9 | import javax.crypto.SecretKey; 10 | import javax.crypto.spec.SecretKeySpec; 11 | import java.util.Arrays; 12 | import java.util.zip.CRC32; 13 | import java.util.zip.Checksum; 14 | 15 | import static org.apache.commons.codec.digest.MessageDigestAlgorithms.SHA_224; 16 | 17 | /** 18 | * Encryption functions 19 | * 20 | * @author linux_china 21 | */ 22 | public class EncryptionFunctions { 23 | 24 | 25 | public static String hex(byte[] text) { 26 | return Hex.encodeHexString(text); 27 | } 28 | 29 | public static byte[] unhex(String text) throws Exception { 30 | return Hex.decodeHex(text); 31 | } 32 | 33 | public static String password(byte[] text) throws Exception { 34 | return "*" + sha1(unhex(sha1(text))); 35 | } 36 | 37 | public static String base64(String text) throws Exception { 38 | return Base64.encodeBase64String(text.getBytes()); 39 | } 40 | 41 | public static String unbase64(String text) throws Exception { 42 | return new String(Base64.decodeBase64(text.getBytes())); 43 | } 44 | 45 | public static String md5(String text) { 46 | return DigestUtils.md5Hex(text); 47 | } 48 | 49 | public static String sha1(byte[] text) { 50 | return DigestUtils.sha1Hex(text); 51 | } 52 | 53 | public static String sha(byte[] text) { 54 | return sha1(text); 55 | } 56 | 57 | public static String sha2(byte[] text, Integer hashLength) throws Exception { 58 | if (hashLength == 0 || hashLength == 256) { 59 | return DigestUtils.sha256Hex(text); 60 | } else if (hashLength == 224) { 61 | return new DigestUtils(SHA_224).digestAsHex(text); 62 | } else if (hashLength == 384) { 63 | return DigestUtils.sha384Hex(text); 64 | } else if (hashLength == 512) { 65 | return DigestUtils.sha512Hex(text); 66 | } 67 | return null; 68 | } 69 | 70 | public static byte[] randomBytes(Integer length) { 71 | if (length > 0 && length < 1024) { 72 | return RandomUtils.nextBytes(length); 73 | } 74 | return null; 75 | } 76 | 77 | public static byte[] aesEncrypt(byte[] text, byte[] password) throws Exception { 78 | Cipher cipher = Cipher.getInstance("AES"); 79 | cipher.init(Cipher.ENCRYPT_MODE, generateSecretKey(password)); 80 | return cipher.doFinal(text); 81 | } 82 | 83 | public static Long crc32(String text) { 84 | if (text == null) return null; 85 | byte[] bytes = text.getBytes(); 86 | Checksum checksum = new CRC32(); 87 | checksum.update(bytes, 0, bytes.length); 88 | return checksum.getValue(); 89 | } 90 | 91 | public static byte[] createDigest(String digestType, String text) { 92 | return new DigestUtils(digestType.replace("SHA", "SHA-")).digest(text); 93 | } 94 | 95 | public static String aesDecrypt(byte[] content, byte[] password) throws Exception { 96 | Cipher cipher = Cipher.getInstance("AES"); 97 | cipher.init(Cipher.DECRYPT_MODE, generateSecretKey(password)); 98 | return new String(cipher.doFinal(content)); 99 | } 100 | 101 | private static SecretKey generateSecretKey(byte[] password) { 102 | return new SecretKeySpec(Arrays.copyOfRange(DigestUtils.sha1(password), 0, 16), "AES"); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V0__functions.sql: -------------------------------------------------------------------------------- 1 | -- date & time 2 | CREATE ALIAS IF NOT EXISTS UNIX_TIMESTAMP FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.unixTimestamp"; 3 | CREATE ALIAS FROM_UNIXTIME FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.fromUnixTime"; 4 | CREATE ALIAS ADDDATE FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.addDate"; 5 | CREATE ALIAS ADDTIME FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.addTime"; 6 | CREATE ALIAS DATE FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.date"; 7 | CREATE ALIAS TIME FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.time"; 8 | CREATE ALIAS UTC_TIMESTAMP FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.utcTimestamp"; 9 | CREATE ALIAS UTC_DATE FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.utcDate"; 10 | CREATE ALIAS UTC_TIME FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.utcTime"; 11 | CREATE ALIAS FROM_DAYS FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.fromDays"; 12 | CREATE ALIAS TO_DAYS FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.toDays"; 13 | CREATE ALIAS TO_SECONDS FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.toSeconds"; 14 | CREATE ALIAS TIME_TO_SEC FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.timeToSeconds"; 15 | CREATE ALIAS DATE_FORMAT FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.dateFormat"; 16 | CREATE ALIAS TIME_FORMAT FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.timeFormat"; 17 | CREATE ALIAS LAST_DAY FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.lastDay"; 18 | CREATE ALIAS MAKEDATE FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.makeDate"; 19 | CREATE ALIAS MAKETIME FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.makeTime"; 20 | CREATE ALIAS SEC_TO_TIME FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.secondsToTime"; 21 | CREATE ALIAS SLEEP FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.sleep"; 22 | CREATE ALIAS STR_TO_DATE FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.strToDate"; 23 | CREATE ALIAS SUBDATE FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.subDate"; 24 | CREATE ALIAS SUBTIME FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.subTime"; 25 | CREATE ALIAS YEARWEEK FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.yearWeek"; 26 | CREATE ALIAS WEEKOFYEAR FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.weekOfYear"; 27 | CREATE ALIAS WEEKDAY FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.weekDay"; 28 | CREATE ALIAS MICROSECOND FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.microSecond"; 29 | CREATE ALIAS CONVERT_TZ FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.convertTZ"; 30 | CREATE ALIAS PERIOD_ADD FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.periodAdd"; 31 | CREATE ALIAS PERIOD_DIFF FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.periodDiff"; 32 | CREATE ALIAS TIMEDIFF FOR "org.mvnsearch.h2.mysql.DateTimeFunctions.timeDiff"; 33 | -- encrypt 34 | CREATE ALIAS MD5 FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.md5"; 35 | CREATE ALIAS SHA1 FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.sha1"; 36 | CREATE ALIAS SHA FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.sha"; 37 | CREATE ALIAS HEX FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.hex"; 38 | CREATE ALIAS UNHEX FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.unhex"; 39 | CREATE ALIAS PASSWORD FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.password"; 40 | CREATE ALIAS TO_BASE64 FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.base64"; 41 | CREATE ALIAS FROM_BASE64 FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.unbase64"; 42 | CREATE ALIAS RANDOM_BYTES FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.randomBytes"; 43 | CREATE ALIAS AES_ENCRYPT FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.aesEncrypt"; 44 | CREATE ALIAS AES_DECRYPT FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.aesDecrypt"; 45 | CREATE ALIAS CRC32 FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.crc32"; 46 | CREATE ALIAS CREATE_DIGEST FOR "org.mvnsearch.h2.mysql.EncryptionFunctions.createDigest"; 47 | -- string functions 48 | CREATE ALIAS BIN FOR "org.mvnsearch.h2.mysql.StringFunctions.bin"; 49 | CREATE ALIAS UUID_SHORT FOR "org.mvnsearch.h2.mysql.StringFunctions.uuidShort"; 50 | CREATE ALIAS FIND_IN_SET FOR "org.mvnsearch.h2.mysql.StringFunctions.findInSet"; 51 | CREATE ALIAS IS_IPV4 FOR "org.mvnsearch.h2.mysql.StringFunctions.isIpv4"; 52 | CREATE ALIAS IS_IPV6 FOR "org.mvnsearch.h2.mysql.StringFunctions.isIpv6"; 53 | CREATE ALIAS IS_UUID FOR "org.mvnsearch.h2.mysql.StringFunctions.isUUID"; 54 | CREATE ALIAS REVERSE FOR "org.mvnsearch.h2.mysql.StringFunctions.reverse"; 55 | CREATE ALIAS SUBSTRING_INDEX FOR "org.mvnsearch.h2.mysql.StringFunctions.subStringIndex"; 56 | CREATE ALIAS STRCMP FOR "org.mvnsearch.h2.mysql.StringFunctions.strCmp"; 57 | CREATE ALIAS CHARSET FOR "org.mvnsearch.h2.mysql.StringFunctions.charset"; 58 | CREATE ALIAS FIELD FOR "org.mvnsearch.h2.mysql.StringFunctions.field"; 59 | CREATE ALIAS MID FOR "org.mvnsearch.h2.mysql.StringFunctions.mid"; 60 | CREATE ALIAS ORD FOR "org.mvnsearch.h2.mysql.StringFunctions.ord"; 61 | CREATE ALIAS QUOTE FOR "org.mvnsearch.h2.mysql.StringFunctions.quote"; 62 | -- math functions 63 | CREATE ALIAS POW FOR "org.mvnsearch.h2.mysql.MathFunctions.pow"; 64 | CREATE ALIAS CONV FOR "org.mvnsearch.h2.mysql.MathFunctions.conv"; 65 | -- misc 66 | CREATE ALIAS FORMAT FOR "org.mvnsearch.h2.mysql.MiscFunctions.format"; 67 | CREATE ALIAS VERSION FOR "org.mvnsearch.h2.mysql.MiscFunctions.version"; 68 | CREATE ALIAS CONNECTION_ID FOR "org.mvnsearch.h2.mysql.MiscFunctions.connectId"; 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/h2/mysql/StringFunctions.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.h2.mysql; 2 | 3 | import org.apache.commons.lang3.RandomUtils; 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import java.io.*; 7 | import java.util.Arrays; 8 | import java.util.regex.Pattern; 9 | import java.util.zip.DeflaterOutputStream; 10 | import java.util.zip.InflaterInputStream; 11 | 12 | /** 13 | * String functions 14 | * 15 | * @author linux_china 16 | */ 17 | public class StringFunctions { 18 | private static final Pattern IP_ADDRESS_PATTERN = Pattern.compile( 19 | "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + 20 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + 21 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + 22 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"); 23 | 24 | public static String bin(Long number) { 25 | return Long.toBinaryString(number); 26 | } 27 | 28 | public static Long uuidShort() { 29 | return RandomUtils.nextLong(Long.MAX_VALUE / 2, Long.MAX_VALUE); 30 | } 31 | 32 | public static Integer findInSet(String str, String strSet) { 33 | if (str == null || strSet == null) return null; 34 | if (strSet.isEmpty()) return 0; 35 | return Arrays.asList(strSet.split(",")).indexOf(str) + 1; 36 | } 37 | 38 | public static Integer isIpv4(String ip) { 39 | return IP_ADDRESS_PATTERN.matcher(ip).matches() ? 1 : 0; 40 | } 41 | 42 | public static Integer isIpv6(String ip) { 43 | return ip.matches("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$") 44 | || ip.matches("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$") 45 | ? 1 : 0; 46 | 47 | } 48 | 49 | public static Integer isUUID(String uuid) { 50 | return uuid.matches("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$") ? 1 : 0; 51 | } 52 | 53 | public static String reverse(String text) { 54 | return new StringBuilder(text).reverse().toString(); 55 | } 56 | 57 | public static String subStringIndex(String text, String delim, Integer count) { 58 | String newDelim = delim; 59 | if (delim.contains(".")) { 60 | newDelim = StringUtils.replace(delim, ".", "\\."); 61 | } 62 | String[] parts = text.split(newDelim); 63 | if (count > 0) { 64 | return String.join(delim, Arrays.copyOfRange(parts, 0, count < parts.length ? count : parts.length)); 65 | } else { 66 | return String.join(delim, Arrays.copyOfRange(parts, parts.length + count < 0 ? 0 : parts.length + count, parts.length)); 67 | } 68 | } 69 | 70 | public static Integer strCmp(String text1, String text2) { 71 | return text1.compareTo(text2); 72 | } 73 | 74 | public static String charset(String text) { 75 | return "utf-8"; 76 | } 77 | 78 | public static String mid(String text, Integer start) { 79 | return text.substring(start); 80 | } 81 | 82 | public static String mid(String text, Integer start, Integer length) { 83 | int newStart = start; 84 | if (start < 0) { 85 | newStart = start + text.length(); 86 | if (newStart < 0) { 87 | newStart = 0; 88 | } 89 | } 90 | int end = newStart + length; 91 | if (end > text.length()) { 92 | end = text.length(); 93 | } 94 | return text.substring(newStart, end); 95 | } 96 | 97 | public static Integer field(String... args) { 98 | for (int i = 1; i < args.length; i++) { 99 | if (args[i].equals(args[0])) { 100 | return i; 101 | } 102 | } 103 | return 0; 104 | } 105 | 106 | public static Long ord(String text) { 107 | int character = text.charAt(0); 108 | if (character < 256) { 109 | return (long) character; 110 | } else { 111 | long sum = 0; 112 | long step = 1; 113 | byte[] bytes = text.getBytes(); 114 | for (byte aByte : bytes) { 115 | sum = sum + aByte * step; 116 | step = step * 256; 117 | } 118 | return sum; 119 | } 120 | } 121 | 122 | public static String quote(String text) { 123 | String text2 = StringUtils.replace(text, "'", "''"); 124 | return StringUtils.replace(text2, "\\", "\\\\"); 125 | } 126 | 127 | public static byte[] compress(String text) throws Exception { 128 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 129 | OutputStream out = new DeflaterOutputStream(bos); 130 | ByteArrayInputStream in = new ByteArrayInputStream(text.getBytes()); 131 | shovelInToOut(in, out); 132 | in.close(); 133 | out.close(); 134 | return bos.toByteArray(); 135 | } 136 | 137 | public static String unCompress(byte[] compressed) throws Exception { 138 | InputStream in = 139 | new InflaterInputStream(new ByteArrayInputStream(compressed)); 140 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 141 | shovelInToOut(in, out); 142 | in.close(); 143 | out.close(); 144 | return new String(out.toByteArray()); 145 | } 146 | 147 | /** 148 | * Shovels all data from an input stream to an output stream. 149 | */ 150 | private static void shovelInToOut(InputStream in, OutputStream out) 151 | throws IOException { 152 | byte[] buffer = new byte[1000]; 153 | int len; 154 | while ((len = in.read(buffer)) > 0) { 155 | out.write(buffer, 0, len); 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | org.mvnsearch 6 | h2-functions-4-mysql 7 | 2.0.0 8 | jar 9 | 10 | h2-functions-4-mysql 11 | https://github.com/linux-china/h2-functions-4-mysql 12 | H2 user defined functions for MySQL compatible 13 | 14 | 15 | 1.8 16 | ${java.version} 17 | ${java.version} 18 | UTF-8 19 | 20 | 21 | 22 | 23 | The Apache License, Version 2.0 24 | https://www.apache.org/licenses/LICENSE-2.0.txt 25 | 26 | 27 | 28 | 29 | scm:git:git@github.com:linux-china/h2-functions-4-mysql.git 30 | scm:git:git@github.com:linux-china/h2-functions-4-mysql.git 31 | https://github.com/linux-china/h2-functions-4-mysql 32 | 33 | 34 | 35 | 36 | ossrh 37 | https://oss.sonatype.org/content/repositories/snapshots 38 | 39 | 40 | ossrh 41 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 42 | 43 | 44 | 45 | 46 | 47 | linux_china 48 | Jacky Chan 49 | libing.chen@gmail.com 50 | https://twitter.com/linux_china 51 | 52 | Developer 53 | 54 | 55 | 56 | 57 | 58 | 59 | com.h2database 60 | h2 61 | 2.2.224 62 | 63 | 64 | commons-codec 65 | commons-codec 66 | 1.15 67 | 68 | 69 | org.apache.commons 70 | commons-lang3 71 | 3.12.0 72 | 73 | 74 | junit 75 | junit 76 | 4.13.2 77 | test 78 | 79 | 80 | commons-io 81 | commons-io 82 | 2.11.0 83 | test 84 | 85 | 86 | 87 | 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-compiler-plugin 92 | 3.11.0 93 | 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | release 103 | 104 | 105 | 106 | org.sonatype.plugins 107 | nexus-staging-maven-plugin 108 | 1.6.8 109 | true 110 | 111 | ossrh 112 | https://oss.sonatype.org/ 113 | true 114 | 115 | 116 | 117 | org.apache.maven.plugins 118 | maven-source-plugin 119 | 3.2.1 120 | 121 | 122 | attach-sources 123 | 124 | jar-no-fork 125 | 126 | 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-javadoc-plugin 132 | 3.1.1 133 | 134 | 135 | attach-javadocs 136 | 137 | jar 138 | 139 | 140 | 141 | 142 | 143 | org.apache.maven.plugins 144 | maven-gpg-plugin 145 | 1.6 146 | 147 | 148 | sign-artifacts 149 | verify 150 | 151 | sign 152 | 153 | 154 | 155 | --pinentry-mode 156 | loopback 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/h2/mysql/DateTimeFunctions.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.h2.mysql; 2 | 3 | import org.apache.commons.lang3.time.DateFormatUtils; 4 | import org.apache.commons.lang3.time.DateUtils; 5 | 6 | import java.sql.Date; 7 | import java.sql.Time; 8 | import java.sql.Timestamp; 9 | import java.time.*; 10 | import java.time.temporal.ChronoUnit; 11 | import java.time.temporal.TemporalAdjusters; 12 | import java.time.temporal.WeekFields; 13 | import java.util.HashMap; 14 | import java.util.Locale; 15 | import java.util.Map; 16 | 17 | /** 18 | * date time functions for mysql 19 | * 20 | * @author linux_china 21 | */ 22 | public class DateTimeFunctions { 23 | public static LocalDateTime ZERO_START_TIME = LocalDateTime.of(0, 1, 1, 0, 0, 0); 24 | public static LocalDateTime UNIX_START_TIME = LocalDateTime.of(1970, 1, 1, 0, 0, 0); 25 | public static ZoneOffset DEFAULT_ZONE_OFFSET = OffsetDateTime.now().getOffset(); 26 | 27 | /** 28 | * function for UNIX_TIMESTAMP 29 | * 30 | * @return current time millis 31 | */ 32 | public static Long unixTimestamp() { 33 | return System.currentTimeMillis(); 34 | } 35 | 36 | /** 37 | * function for UNIX_TIMESTAMP 38 | * 39 | * @return current time millis 40 | */ 41 | public static Long unixTimestamp(Timestamp timestamp) throws Exception { 42 | return timestamp.getTime(); 43 | } 44 | 45 | public static LocalDateTime fromUnixTime(Long unixTime) { 46 | return LocalDateTime.ofEpochSecond(unixTime, 0, DEFAULT_ZONE_OFFSET); 47 | } 48 | 49 | public static Date addDate(Timestamp date, Integer days) throws Exception { 50 | return new Date(date.getTime() + days * 24 * 60 * 60 * 1000); 51 | } 52 | 53 | public static Date subDate(Timestamp date, Integer days) throws Exception { 54 | return new Date(date.getTime() - days * 24L * 60L * 60L * 1000L); 55 | } 56 | 57 | public static Date addTime(Timestamp date, String timeText) throws Exception { 58 | java.util.Date time = DateUtils.parseDate(timeText, "HH:mm:ss", "HH:mm:ss.S", "dd HH:mm:ss", "dd HH:mm:ss.S"); 59 | return new Date(date.getTime() + time.getTime()); 60 | } 61 | 62 | public static Date subTime(Timestamp date, String timeText) throws Exception { 63 | java.util.Date time = DateUtils.parseDate(timeText, "HH:mm:ss", "HH:mm:ss.S", "dd HH:mm:ss", "dd HH:mm:ss.S"); 64 | return new Date(date.getTime() - time.getTime()); 65 | } 66 | 67 | public static Date date(Timestamp date) throws Exception { 68 | return new Date(date.getTime()); 69 | } 70 | 71 | public static LocalDateTime utcTimestamp() { 72 | return ZonedDateTime.now(ZoneId.of("UTC")).toLocalDateTime(); 73 | } 74 | 75 | public static LocalDate utcDate() { 76 | return ZonedDateTime.now(ZoneId.of("UTC")).toLocalDate(); 77 | } 78 | 79 | public static LocalTime utcTime() { 80 | return ZonedDateTime.now(ZoneId.of("UTC")).toLocalTime(); 81 | } 82 | 83 | public static Date sysDate() { 84 | return new Date(System.currentTimeMillis()); 85 | } 86 | 87 | public static LocalDate fromDays(Integer days) { 88 | return ZERO_START_TIME.plusDays(days).toLocalDate(); 89 | } 90 | 91 | public static Long toDays(Date date) throws Exception { 92 | LocalDate startDate = ZERO_START_TIME.toLocalDate(); 93 | LocalDate endDate = date.toLocalDate(); 94 | return (ChronoUnit.DAYS.between(startDate, endDate)); 95 | } 96 | 97 | public static Long toSeconds(Timestamp date) throws Exception { 98 | long days = ChronoUnit.DAYS.between(ZERO_START_TIME.toLocalDate(), UNIX_START_TIME.toLocalDate()); 99 | return date.getTime() / 1000 + days * 24 * 60 * 60; 100 | } 101 | 102 | public static Long timeToSeconds(Time time) throws Exception { 103 | return time.getTime() / 1000; 104 | } 105 | 106 | public static String secondsToTime(Integer totalSeconds) { 107 | long seconds = totalSeconds % 60; 108 | long minutes = totalSeconds / 60 % 60; 109 | long hours = totalSeconds / (3600) % 24; 110 | return padNumber(hours) + ":" + padNumber(minutes) + ":" + padNumber(seconds); 111 | } 112 | 113 | public static Time time(Timestamp date) throws Exception { 114 | return new Time(date.getTime()); 115 | } 116 | 117 | public static String dateFormat(Timestamp date, String mysqlPattern) throws Exception { 118 | String javaPattern = mysqlPattern; 119 | for (Map.Entry entry : mysqlToJavaDateFormat().entrySet()) { 120 | javaPattern = javaPattern.replace(entry.getKey(), entry.getValue()); 121 | } 122 | return DateFormatUtils.format(date, javaPattern); 123 | } 124 | 125 | public static String timeFormat(Time time, String mysqlPattern) throws Exception { 126 | String javaPattern = mysqlPattern; 127 | for (Map.Entry entry : mysqlToJavaDateFormat().entrySet()) { 128 | javaPattern = javaPattern.replace(entry.getKey(), entry.getValue()); 129 | } 130 | return DateFormatUtils.format(time, javaPattern); 131 | } 132 | 133 | public static LocalDate lastDay(Timestamp dateTime) throws Exception { 134 | LocalDate localDate = dateTime.toLocalDateTime().toLocalDate(); 135 | return localDate.with(TemporalAdjusters.lastDayOfMonth()); 136 | } 137 | 138 | public static Date makeDate(Integer year, Integer days) { 139 | LocalDateTime start = LocalDateTime.of(year, 1, 1, 0, 0, 0); 140 | LocalDateTime end = start.plusDays(days - 1); 141 | return Date.valueOf(end.toLocalDate()); 142 | } 143 | 144 | public static String makeTime(Integer hours, Integer minutes, Integer seconds) { 145 | return padNumber((long) hours) + ":" + padNumber((long) minutes) + ":" + padNumber((long) seconds); 146 | } 147 | 148 | public static Integer sleep(Integer seconds) throws Exception { 149 | Thread.sleep(seconds * 1000); 150 | return 0; 151 | } 152 | 153 | public static String strToDate(String dateStr, String mysqlPattern) throws Exception { 154 | String javaPattern = mysqlPattern; 155 | for (Map.Entry entry : mysqlToJavaDateFormat().entrySet()) { 156 | javaPattern = javaPattern.replace(entry.getKey(), entry.getValue()); 157 | } 158 | java.util.Date date = DateUtils.parseDate(dateStr, javaPattern); 159 | if (mysqlPattern.toLowerCase().contains("%y")) { 160 | return DateFormatUtils.format(date, "yyyy-MM-dd"); 161 | } else { 162 | return DateFormatUtils.format(date, "HH:mm:ss"); 163 | } 164 | } 165 | 166 | public static Integer yearWeek(Timestamp timestamp, Integer mode) throws Exception { 167 | LocalDate localDate = timestamp.toLocalDateTime().toLocalDate(); 168 | int day = localDate.getDayOfWeek().getValue(); 169 | if (day > 0) { 170 | localDate = localDate.minusDays(day); 171 | } 172 | int year = localDate.getYear(); 173 | int offset = mode == 0 ? 1 : 0; 174 | int weekNumber = localDate.get(WeekFields.of(Locale.getDefault()).weekOfYear()) - offset; 175 | return year * 100 + weekNumber; 176 | } 177 | 178 | 179 | public static Integer yearWeek(Timestamp timestamp) throws Exception { 180 | return yearWeek(timestamp, 0); 181 | } 182 | 183 | public static Integer weekOfYear(Timestamp timestamp) throws Exception { 184 | LocalDate localDate = timestamp.toLocalDateTime().toLocalDate(); 185 | return localDate.get(WeekFields.of(Locale.getDefault()).weekOfYear()); 186 | } 187 | 188 | public static Integer weekDay(Timestamp timestamp) throws Exception { 189 | LocalDate localDate = timestamp.toLocalDateTime().toLocalDate(); 190 | int firstDayOfWeek = WeekFields.of(Locale.getDefault()).getFirstDayOfWeek().getValue(); 191 | if (firstDayOfWeek == 7) { 192 | return localDate.get(WeekFields.of(Locale.getDefault()).dayOfWeek()) - 2; 193 | } else { 194 | return localDate.get(WeekFields.of(Locale.getDefault()).dayOfWeek()) - 1; 195 | } 196 | } 197 | 198 | public static Long microSecond(Time time) throws Exception { 199 | return time.getTime() / 1000; 200 | 201 | } 202 | 203 | public static String convertTZ(Timestamp date, String originTZ, String targetTZ) throws Exception { 204 | ZoneId zoneId; 205 | try { 206 | zoneId = ZoneId.of(targetTZ); 207 | } catch (Exception e) { 208 | zoneId = ZoneOffset.of(targetTZ); 209 | } 210 | LocalDate localDate = date.toInstant().atZone(zoneId).toLocalDate(); 211 | return DateFormatUtils.format(Date.valueOf(localDate), "yyyy-MM-dd HH:mm:ss"); 212 | } 213 | 214 | public static Integer periodAdd(Integer yearAndMonth, Integer months) throws Exception { 215 | String text = String.valueOf(yearAndMonth); 216 | java.util.Date date = DateUtils.parseDate(text, "yyyyMM", "yyMM"); 217 | LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); 218 | LocalDate newDate = localDate.plusMonths(months); 219 | return newDate.getYear() * 100 + newDate.getMonthValue(); 220 | } 221 | 222 | public static Integer periodDiff(Integer yearAndMonth1, Integer yearAndMonth2) { 223 | int months1 = ((yearAndMonth1 / 100) * 12) + yearAndMonth1 % 100; 224 | int months2 = ((yearAndMonth2 / 100) * 12) + yearAndMonth2 % 100; 225 | return months1 - months2; 226 | } 227 | 228 | public static String timeDiff(Timestamp date1, Timestamp date2) throws Exception { 229 | String sign = ""; 230 | if (date1.getTime() < date2.getTime()) { 231 | sign = "-"; 232 | } 233 | Long totalMilliSeconds = Math.abs(date1.getTime() - date2.getTime()); 234 | long milliSeconds = totalMilliSeconds % 1000; 235 | Long seconds = totalMilliSeconds / 1000 / 60 % 60; 236 | Long minutes = totalMilliSeconds / 1000 / 3600 % 60; 237 | long hours = totalMilliSeconds / 1000 / 3600; 238 | return sign + hours + ":" + padNumber(minutes) + ":" + padNumber(seconds) + "." + milliSeconds; 239 | } 240 | 241 | private static String padNumber(Long number) { 242 | if (number < 10L) return "0" + number; 243 | return String.valueOf(number); 244 | } 245 | 246 | private static Map mysqlToJavaDateFormat() { 247 | Map convert = new HashMap<>(); 248 | convert.put("%a", "E"); 249 | convert.put("%b", "M"); 250 | convert.put("%c", "M"); 251 | convert.put("%d", "dd"); 252 | convert.put("%e", "d"); 253 | convert.put("%f", "S"); 254 | convert.put("%H", "HH"); 255 | convert.put("%h", "H"); 256 | convert.put("%I", "h"); 257 | convert.put("%i", "mm"); 258 | convert.put("%J", "D"); 259 | convert.put("%k", "h"); 260 | convert.put("%l", "h"); 261 | convert.put("%M", "M"); 262 | convert.put("%m", "MM"); 263 | convert.put("%p", "a"); 264 | convert.put("%r", "hh:mm:ss a"); 265 | convert.put("%s", "ss"); 266 | convert.put("%S", "ss"); 267 | convert.put("%T", "HH:mm:ss"); 268 | convert.put("%U", "w"); 269 | convert.put("%u", "w"); 270 | convert.put("%V", "w"); 271 | convert.put("%v", "w"); 272 | convert.put("%W", "EEE"); 273 | convert.put("%w", "F"); 274 | convert.put("%Y", "yyyy"); 275 | convert.put("%y", "yy"); 276 | return convert; 277 | } 278 | 279 | } 280 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021 linux_china 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | h2-functions-4-mysql 2 | ====================== 3 | 4 | ![Version](https://img.shields.io/maven-central/v/org.mvnsearch/h2-functions-4-mysql) 5 | 6 | H2 User defined functions for MySQL. 7 | 8 | # Why this project? 9 | 10 | I always use H2 for unit test instead of real MySQL(Docker), but some MySQL functions are not available in H2. So I create this project to define some functions for MySQL and make 11 | unit test easy. 12 | 13 | # How to use? 14 | 15 | In you pom.xml add following dependency: 16 | 17 | For H2 1.4.x, please use 1.0.0 version as following: 18 | 19 | ```xml 20 | 21 | 22 | org.mvnsearch 23 | h2-functions-4-mysql 24 | 1.0.0 25 | 26 | ``` 27 | 28 | For H2 2.0.x, please use 2.0.0 version as following: 29 | 30 | ```xml 31 | 32 | 33 | org.mvnsearch 34 | h2-functions-4-mysql 35 | 2.0.0 36 | 37 | ``` 38 | 39 | * Flyway with Spring Boot: automatically(classpath:db/migration/h2/V0_functions.sql), no configuration. 40 | * Manual: Add following code in your application. datasource is h2 datasource. 41 | 42 | ``` 43 | H2FunctionsLoader.loadMysqlFunctions(dataSource); 44 | ``` 45 | 46 | * From H2 210, and you can use INIT parameter to load functions automatically. 47 | 48 | ``` 49 | String jdbcUrl = "jdbc:h2:mem:sample;INIT=RUNSCRIPT FROM 'classpath:db/migration/h2/V0_functions.sql'"; 50 | String jdbcUrl2 = "jdbc:h2:mem:sample;INIT=RUNSCRIPT FROM 'classpath:db/migration/h2/V0_functions.sql';RUNSCRIPT FROM 'classpath:your_script.sql'"; 51 | ``` 52 | 53 | ## Function List 54 | 55 | N: not available, Y: same, A: available 56 | 57 | | MySQL | H2 | Status | 58 | |:------------------|:-----------------:|---------------------------------------------------------:| 59 | | ABS | ABS | Y | 60 | | ACOS | ACOS | Y | 61 | | ADDDATE || A | 62 | | ADDTIME || A | 63 | | AES_DECRYPT || A | 64 | | AES_ENCRYPT || A | 65 | | ANY_VALUE || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 66 | | ASCII | ASCII | Y | 67 | | ASIN | ASIN | Y | 68 | | ATAN | ATAN | Y | 69 | | ATAN2 | ATAN2 | Y | 70 | | AVG | AVG | Y | 71 | | BENCHMARK || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 72 | | BIN || A | 73 | | BIN_TO_UUID || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 74 | | BIT_AND | BIT_AND | Y | 75 | | BIT_COUNT || N | 76 | | BIT_LENGTH | BIT_LENGTH | Y | 77 | | BIT_OR | BIT_OR | Y | 78 | | BIT_XOR || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 79 | | CAST | CAST | Y | 80 | | CEIL | CEIL | Y | 81 | | CEILING | CEILING | Y | 82 | | CHAR | CHAR | Y | 83 | | CHAR_LENGTH | CHAR_LENGTH | Y | 84 | | CHARACTER_LENGTH | CHARACTER_LENGTH | Y | 85 | | CHARSET || A | 86 | | COALESCE | COALESCE | Y | 87 | | COERCIBILITY || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 88 | | COLLATION || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 89 | | COMPRESS | COMPRESS | Y | 90 | | CONCAT | CONCAT | Y | 91 | | CONCAT_WS | CONCAT_WS | Y | 92 | | CONNECTION_ID || A | 93 | | CONV || A | 94 | | CONVERT | CONVERT | Y | 95 | | CONVERT_TZ || A | 96 | | COS | COS | Y | 97 | | COT | COT | Y | 98 | | COUNT | COUNT | Y | 99 | | COUNT | COUNT | Y | 100 | | CRC32 || A | 101 | | CREATE_DH_PARAMETERS || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 102 | | CREATE_DIGEST || A | 103 | | CUME_DIST || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 104 | | CURDATE | CURDATE | Y | 105 | | CURRENT_DATE | CURRENT_DATE | Y | 106 | | CURRENT_ROLE || A | 107 | | CURRENT_TIME | CURRENT_TIME | Y | 108 | | CURRENT_TIMESTAMP | CURRENT_TIMESTAMP | Y | 109 | | CURRENT_USER || A | 110 | | CURTIME | CURTIME | Y | 111 | | DATABASE | DATABASE | Y | 112 | | DATE || A | 113 | | DATE_ADD || A | 114 | | DATE_FORMAT || A | 115 | | DATE_SUB || A | 116 | | DATEDIFF | DATEDIFF | Y | 117 | | DAY | DAY | Y | 118 | | DAYNAME | DAYNAME | Y | 119 | | DAYOFMONTH | DAYOFMONTH | Y | 120 | | DAYOFWEEK | DAYOFWEEK | Y | 121 | | DAYOFYEAR | DAYOFYEAR | Y | 122 | | DECODE | DECODE | Y | 123 | | DEFAULT || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 124 | | DEGREES | DEGREES | Y | 125 | | DENSE_RANK || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 126 | | DES_DECRYPT || Deprecated | 127 | | DES_ENCRYPT || Deprecated | 128 | | ELT || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 129 | | ENCODE || Deprecated | 130 | | ENCRYPT | ENCRYPT | Y | 131 | | EXP | EXP | Y | 132 | | EXPORT_SET || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 133 | | EXTRACT | EXTRACT | Y | 134 | | ExtractValue || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 135 | | FIELD || A | 136 | | FIND_IN_SET || A | 137 | | FIRST_VALUE || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 138 | | FLOOR | FLOOR | Y | 139 | | FORMAT || A | 140 | | FOUND_ROWS || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 141 | | FROM_BASE64 || A | 142 | | FROM_DAYS || A | 143 | | FROM_UNIXTIME || A | 144 | | GeomCollection || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 145 | | GeometryCollection || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 146 | | GET_DD_COLUMN_PRIVILEGES || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 147 | | GET_DD_CREATE_OPTIONS || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 148 | | GET_DD_INDEX_SUB_PART_LENGTH || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 149 | | GET_FORMAT || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 150 | | GET_LOCK || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 151 | | GREATEST | GREATEST | Y | 152 | | GROUP_CONCAT | GROUP_CONCAT | Y | 153 | | GTID_SUBSET || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 154 | | GTID_SUBTRACT || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 155 | | HEX || A | 156 | | HOUR | HOUR | Y | 157 | | ICU_VERSION || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 158 | | IF || N | 159 | | IFNULL | IFNULL | Y | 160 | | INET_ATON || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 161 | | INET_NTOA || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 162 | | INET6_ATON || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 163 | | INET6_NTOA || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 164 | | INSERT | INSERT | Y | 165 | | INSTR | INSTR | Y | 166 | | INTERVAL || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 167 | | IS_FREE_LOCK || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 168 | | IS_IPV4 || A | 169 | | IS_IPV4_COMPAT || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 170 | | IS_IPV4_MAPPED || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 171 | | IS_IPV6 || A | 172 | | IS_USED_LOCK || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 173 | | IS_UUID || A | 174 | | ISNULL || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 175 | | LAG || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 176 | | LAST_INSERT_ID | LAST_INSERT_ID | Y | 177 | | LAST_VALUE || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 178 | | LCASE | LCASE | Y | 179 | | LEAD || N | 180 | | LEAST | LEAST | Y | 181 | | LEFT | LEFT | Y | 182 | | LENGTH | LENGTH | Y | 183 | | LineString || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 184 | | LN | LN | Y | 185 | | LOAD_FILE || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 186 | | LOCALTIME || A | 187 | | LOCALTIMESTAMP || A | 188 | | LOCATE | LOCATE | Y | 189 | | LOG | LOG | Y | 190 | | LOG10 | LOG10 | Y | 191 | | LOG2 || N | 192 | | LOWER | LOWER | Y | 193 | | LPAD | LPAD | Y | 194 | | LTRIM | LTRIM | Y | 195 | | MAKE_SET || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 196 | | MAKEDATE || A | 197 | | MAKETIME || Y | 198 | | MASTER_POS_WAIT || N | 199 | | MAX | MAX | Y | 200 | | MBRContains || N | 201 | | MBRCoveredBy || N | 202 | | MBRCovers || N | 203 | | MBRDisjoint || N | 204 | | MBREquals || N | 205 | | MBRIntersects || N | 206 | | MBROverlaps || N | 207 | | MBRTouches || N | 208 | | MBRWithin || N | 209 | | MD5 || A | 210 | | MICROSECOND || A | 211 | | MID || A | 212 | | MIN | MIN | Y | 213 | | MINUTE | MINUTE | Y | 214 | | MOD | MOD | Y | 215 | | MONTH | MONTH | Y | 216 | | MONTHNAME | MONTHNAME | Y | 217 | | MultiLineString || N | 218 | | MultiPoint || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 219 | | MultiPolygon || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 220 | | NAME_CONST || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 221 | | NOW || A | 222 | | NTH_VALUE || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 223 | | NTILE || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 224 | | NULLIF | NULLIF | Y | 225 | | OCT || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 226 | | OCTET_LENGTH | OCTET_LENGTH | Y | 227 | | ORD || A | 228 | | PASSWORD || A | 229 | | PERCENT_RANK || N | 230 | | PERIOD_ADD || A | 231 | | PERIOD_DIFF || A | 232 | | PI | PI | Y | 233 | | Point || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 234 | | Polygon || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 235 | | POSITION | POSITION | Y | 236 | | POW || A | 237 | | POWER | POWER | Y | 238 | | QUARTER | QUARTER | Y | 239 | | QUOTE || A | 240 | | RADIANS | RADIANS | Y | 241 | | RAND | RAND | Y | 242 | | RANDOM_BYTES || A | 243 | | RANK || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 244 | | REGEXP_INSTR || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 245 | | REGEXP_LIKE | REGEXP_LIKE | Y | 246 | | REGEXP_REPLACE | REGEXP_REPLACE | Y | 247 | | REGEXP_SUBSTR || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 248 | | RELEASE_ALL_LOCKS || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 249 | | RELEASE_LOCK || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 250 | | REPEAT | REPEAT | Y | 251 | | REPLACE | REPLACE | Y | 252 | | REVERSE || A | 253 | | RIGHT | RIGHT | Y | 254 | | ROLES_GRAPHML || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 255 | | ROUND | ROUND | Y | 256 | | ROW_COUNT || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 257 | | ROW_NUMBER || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 258 | | RPAD | RPAD | Y | 259 | | RTRIM | RTRIM | Y | 260 | | SCHEMA | SCHEMA | Y | 261 | | SEC_TO_TIME || A | 262 | | SECOND | SECOND | Y | 263 | | SESSION_USER || A | 264 | | SHA1 || A | 265 | | SHA2 || A | 266 | | SIGN | SIGN | Y | 267 | | SIN | SIN | Y | 268 | | SLEEP || A | 269 | | SOUNDEX | SOUNDEX | Y | 270 | | SPACE | SPACE | Y | 271 | | SQRT | SQRT | Y | 272 | | STATEMENT_DIGEST || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 273 | | STATEMENT_DIGEST_TEXT || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 274 | | STD || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 275 | | STDDEV || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 276 | | STDDEV_POP | STDDEV_POP | Y | 277 | | STDDEV_SAMP | STDDEV_SAMP | Y | 278 | | STR_TO_DATE || A | 279 | | STRCMP || A | 280 | | SUBDATE || A | 281 | | SUBSTR | SUBSTR | Y | 282 | | SUBSTRING | SUBSTRING | Y | 283 | | SUBSTRING_INDEX || A | 284 | | SUBTIME || A | 285 | | SUM | SUM | Y | 286 | | SYSDATE | SYSDATE | Y | 287 | | SYSTEM_USER || A | 288 | | TAN | TAN | Y | 289 | | TIME || A | 290 | | TIME_FORMAT || A | 291 | | TIME_TO_SEC || A | 292 | | TIMEDIFF || A | 293 | | TIMESTAMP || A | 294 | | TIMESTAMPADD || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 295 | | TIMESTAMPDIFF || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 296 | | TO_BASE64 || A | 297 | | TO_DAYS || A | 298 | | TO_SECONDS || A | 299 | | TRIM | TRIM | Y | 300 | | TRUNCATE | TRUNCATE | Y | 301 | | UCASE || A | 302 | | UNCOMPRESS || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 303 | | UNCOMPRESSED_LENGTH || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 304 | | UNHEX || A | 305 | | UNIX_TIMESTAMP || A | 306 | | UpdateXML || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 307 | | UPPER | UPPER | Y | 308 | | USER | USER | Y | 309 | | UTC_DATE || A | 310 | | UTC_TIME || A | 311 | | UTC_TIMESTAMP || A | 312 | | UUID | UUID | A | 313 | | UUID_SHORT || A | 314 | | UUID_TO_BIN || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 315 | | VALIDATE_PASSWORD_STRENGTH || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 316 | | VALUES || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 317 | | VAR_POP | VAR_POP | Y | 318 | | VAR_SAMP | VAR_SAMP | Y | 319 | | VARIANCE || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 320 | | VERSION || A | 321 | | WAIT_FOR_EXECUTED_GTID_SET || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 322 | | WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 323 | | WEEK | WEEK | Y | 324 | | WEEKDAY || A | 325 | | WEEKOFYEAR || A | 326 | | WEIGHT_STRING || ![](https://via.placeholder.com/15/f03c15/000000?text=N) | 327 | | YEAR | YEAR | Y | 328 | | YEARWEEK || A | 329 | 330 | # References 331 | 332 | * H2 functions: http://www.h2database.com/html/functions.html 333 | * MySQL functions: https://dev.mysql.com/doc/refman/8.0/en/func-op-summary-ref.html 334 | * application-test.properties with H2 MySQL Mode support 335 | 336 | ```properties 337 | ### datasource 338 | spring.datasource.driver-class-name=org.h2.Driver 339 | spring.datasource.url=jdbc:h2:mem:public;MODE=MYSQL;DATABASE_TO_UPPER=false;INIT=CREATE SCHEMA IF NOT EXISTS public 340 | spring.datasource.username=sa 341 | ``` 342 | --------------------------------------------------------------------------------