{"action":"created","comment":{"url":"https://api.github.com/repos/apache/phoenix/pulls/comments/26682196","id":26682196,"diff_hunk":"@@ -0,0 +1,181 @@\n+/*\n+ * Licensed to the Apache Software Foundation (ASF) under one\n+ * or more contributor license agreements.  See the NOTICE file\n+ * distributed with this work for additional information\n+ * regarding copyright ownership.  The ASF licenses this file\n+ * to you under the Apache License, Version 2.0 (the\n+ * \"License\"); you may not use this file except in compliance\n+ * with the License.  You may obtain a copy of the License at\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+package org.apache.phoenix.expression.util.regex;\n+\n+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;\n+import org.apache.phoenix.schema.SortOrder;\n+import org.jcodings.Encoding;\n+import org.jcodings.specific.UTF8Encoding;\n+import org.joni.Matcher;\n+import org.joni.Option;\n+import org.joni.Regex;\n+\n+import com.google.common.base.Preconditions;\n+\n+public class JONIRegexWrapper {\n+\n+    private static final Encoding PVARCHAR_ENCODING = UTF8Encoding.INSTANCE;\n+\n+    static class JONIPattern extends AbstractBasePattern {\n+\n+        private final Regex pattern;\n+        private boolean isLastMatcherStringNull;\n+        private final String patternString;\n+\n+        JONIPattern(String patternString) {\n+            this(patternString, 0);\n+        }\n+\n+        JONIPattern(String patternString, int flags) {\n+            this.patternString = patternString;\n+            if (patternString != null) {\n+                patternString = replacePatternQuote(patternString);\n+                byte[] patternBytes = patternString.getBytes();\n+                pattern = new Regex(patternBytes, 0, patternBytes.length, flags, PVARCHAR_ENCODING);\n+            } else {\n+                pattern = null;\n+            }\n+            isLastMatcherStringNull = false;\n+        }\n+\n+        public enum ReplaceQuoteMachine {\n+            STOP, ZERO, ONE_BACKSLASH, IN_QUOTE, IN_QUOTE_ONE_BACKSLASH;\n+\n+            ReplaceQuoteMachine next(StringBuilder sb, char ch) {\n+                switch (this) {\n+                case ZERO:\n+                    switch (ch) {\n+                    case '\\\\':\n+                        return ONE_BACKSLASH;\n+                    default:\n+                        sb.append(ch);\n+                        return ZERO;\n+                    }\n+                case ONE_BACKSLASH:\n+                    switch (ch) {\n+                    case 'Q':\n+                        return IN_QUOTE;\n+                    default:\n+                        sb.append('\\\\');\n+                        return ZERO.next(sb, ch);\n+                    }\n+                case IN_QUOTE:\n+                    // add backslashes for .^$*+?()[{\\|\n+                    switch (ch) {\n+                    case '.':\n+                    case '^':\n+                    case '$':\n+                    case '*':\n+                    case '+':\n+                    case '?':\n+                    case '(':\n+                    case ')':\n+                    case '[':\n+                    case '{':\n+                    case '|':\n+                        sb.append('\\\\').append(ch);\n+                        return IN_QUOTE;\n+                    case '\\\\':\n+                        return IN_QUOTE_ONE_BACKSLASH;\n+                    default:\n+                        sb.append(ch);\n+                        return IN_QUOTE;\n+                    }\n+                case IN_QUOTE_ONE_BACKSLASH:\n+                    switch (ch) {\n+                    case 'E':\n+                        return ZERO;\n+                    default:\n+                        sb.append('\\\\');\n+                        return IN_QUOTE.next(sb, ch);\n+                    }\n+                case STOP:\n+                default:\n+                    throw new IllegalArgumentException();\n+                }\n+            }\n+\n+            ReplaceQuoteMachine EOF(StringBuilder sb) {\n+                switch (this) {\n+                case ONE_BACKSLASH:\n+                case IN_QUOTE_ONE_BACKSLASH:\n+                    sb.append('\\\\');\n+                case ZERO:\n+                case IN_QUOTE:\n+                    return STOP;\n+                case STOP:\n+                default:\n+                    throw new IllegalArgumentException();\n+                }\n+            }\n+        }\n+\n+        private String replacePatternQuote(String patternString) {\n+            StringBuilder sb = new StringBuilder();\n+            ReplaceQuoteMachine cur = ReplaceQuoteMachine.ZERO;\n+            for (int i = 0; i < patternString.length(); ++i) {\n+                cur = cur.next(sb, patternString.charAt(i));\n+            }\n+            cur = cur.EOF(sb);\n+            return sb.toString();\n+        }\n+\n+        @Override\n+        public AbstractBaseMatcher macher(ImmutableBytesWritable ptr, SortOrder sortOrder) {\n+            Preconditions.checkNotNull(ptr);\n+            Preconditions.checkNotNull(sortOrder);\n+            byte[] matcherSourceBytes = Utils.immutableBytesWritableToBytes(ptr, sortOrder);","path":"phoenix-core/src/main/java/org/apache/phoenix/expression/util/regex/JONIRegexWrapper.java","position":142,"original_position":142,"commit_id":"740f53d0cdf28300bf94c0a197245874d58005da","original_commit_id":"740f53d0cdf28300bf94c0a197245874d58005da","user":{"login":"JamesRTaylor","id":6176299,"avatar_url":"https://avatars.githubusercontent.com/u/6176299?v=3","gravatar_id":"","url":"https://api.github.com/users/JamesRTaylor","html_url":"https://github.com/JamesRTaylor","followers_url":"https://api.github.com/users/JamesRTaylor/followers","following_url":"https://api.github.com/users/JamesRTaylor/following{/other_user}","gists_url":"https://api.github.com/users/JamesRTaylor/gists{/gist_id}","starred_url":"https://api.github.com/users/JamesRTaylor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JamesRTaylor/subscriptions","organizations_url":"https://api.github.com/users/JamesRTaylor/orgs","repos_url":"https://api.github.com/users/JamesRTaylor/repos","events_url":"https://api.github.com/users/JamesRTaylor/events{/privacy}","received_events_url":"https://api.github.com/users/JamesRTaylor/received_events","type":"User","site_admin":false},"body":"Don't turn ptr into byte[] as it's expensive (it makes a copy of the byte[]). Instead do this below:\r\n\r\n    new JONIMatcher(pattern.matcher(ptr.get(), ptr.getOffset()), ptr.getLength());","created_at":"2015-03-18T16:49:56Z","updated_at":"2015-03-18T16:49:56Z","html_url":"https://github.com/apache/phoenix/pull/46#discussion_r26682196","pull_request_url":"https://api.github.com/repos/apache/phoenix/pulls/46","_links":{"self":{"href":"https://api.github.com/repos/apache/phoenix/pulls/comments/26682196"},"html":{"href":"https://github.com/apache/phoenix/pull/46#discussion_r26682196"},"pull_request":{"href":"https://api.github.com/repos/apache/phoenix/pulls/46"}}},"pull_request":{"url":"https://api.github.com/repos/apache/phoenix/pulls/46","id":31197568,"html_url":"https://github.com/apache/phoenix/pull/46","diff_url":"https://github.com/apache/phoenix/pull/46.diff","patch_url":"https://github.com/apache/phoenix/pull/46.patch","issue_url":"https://api.github.com/repos/apache/phoenix/issues/46","number":46,"state":"open","locked":false,"title":"Draft for PHOENIX-1287 subtask, ByteBasedLikeExpression","user":{"login":"shuxiong","id":1835603,"avatar_url":"https://avatars.githubusercontent.com/u/1835603?v=3","gravatar_id":"","url":"https://api.github.com/users/shuxiong","html_url":"https://github.com/shuxiong","followers_url":"https://api.github.com/users/shuxiong/followers","following_url":"https://api.github.com/users/shuxiong/following{/other_user}","gists_url":"https://api.github.com/users/shuxiong/gists{/gist_id}","starred_url":"https://api.github.com/users/shuxiong/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shuxiong/subscriptions","organizations_url":"https://api.github.com/users/shuxiong/orgs","repos_url":"https://api.github.com/users/shuxiong/repos","events_url":"https://api.github.com/users/shuxiong/events{/privacy}","received_events_url":"https://api.github.com/users/shuxiong/received_events","type":"User","site_admin":false},"body":"Hi @JamesRTaylor ,\r\n\r\nThis is a draft for\r\n1. Abstraction for Regex Engine, byte-based one(JONI) and string-based one(j.u.regex)\r\n2. ByteBasedLikeExpression and StringBasedLikeExpression based on 1.\r\n\r\nComment if you think there is anything to be improved.\r\nThen I will work on other expressions(RegexpReplaceFunction, RegexpSplitFunction, RegexpSubstrFunction) next.\r\n\r\nThanks.","created_at":"2015-03-15T09:06:20Z","updated_at":"2015-03-18T16:49:56Z","closed_at":null,"merged_at":null,"merge_commit_sha":"33de67232ee98b81ca8840064e3fe283a4718f60","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apache/phoenix/pulls/46/commits","review_comments_url":"https://api.github.com/repos/apache/phoenix/pulls/46/comments","review_comment_url":"https://api.github.com/repos/apache/phoenix/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/phoenix/issues/46/comments","statuses_url":"https://api.github.com/repos/apache/phoenix/statuses/740f53d0cdf28300bf94c0a197245874d58005da","head":{"label":"shuxiong:4.3-PHOENIX-1287","ref":"4.3-PHOENIX-1287","sha":"740f53d0cdf28300bf94c0a197245874d58005da","user":{"login":"shuxiong","id":1835603,"avatar_url":"https://avatars.githubusercontent.com/u/1835603?v=3","gravatar_id":"","url":"https://api.github.com/users/shuxiong","html_url":"https://github.com/shuxiong","followers_url":"https://api.github.com/users/shuxiong/followers","following_url":"https://api.github.com/users/shuxiong/following{/other_user}","gists_url":"https://api.github.com/users/shuxiong/gists{/gist_id}","starred_url":"https://api.github.com/users/shuxiong/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shuxiong/subscriptions","organizations_url":"https://api.github.com/users/shuxiong/orgs","repos_url":"https://api.github.com/users/shuxiong/repos","events_url":"https://api.github.com/users/shuxiong/events{/privacy}","received_events_url":"https://api.github.com/users/shuxiong/received_events","type":"User","site_admin":false},"repo":{"id":31898066,"name":"phoenix","full_name":"shuxiong/phoenix","owner":{"login":"shuxiong","id":1835603,"avatar_url":"https://avatars.githubusercontent.com/u/1835603?v=3","gravatar_id":"","url":"https://api.github.com/users/shuxiong","html_url":"https://github.com/shuxiong","followers_url":"https://api.github.com/users/shuxiong/followers","following_url":"https://api.github.com/users/shuxiong/following{/other_user}","gists_url":"https://api.github.com/users/shuxiong/gists{/gist_id}","starred_url":"https://api.github.com/users/shuxiong/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shuxiong/subscriptions","organizations_url":"https://api.github.com/users/shuxiong/orgs","repos_url":"https://api.github.com/users/shuxiong/repos","events_url":"https://api.github.com/users/shuxiong/events{/privacy}","received_events_url":"https://api.github.com/users/shuxiong/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/shuxiong/phoenix","description":"Mirror of Apache Phoenix","fork":true,"url":"https://api.github.com/repos/shuxiong/phoenix","forks_url":"https://api.github.com/repos/shuxiong/phoenix/forks","keys_url":"https://api.github.com/repos/shuxiong/phoenix/keys{/key_id}","collaborators_url":"https://api.github.com/repos/shuxiong/phoenix/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/shuxiong/phoenix/teams","hooks_url":"https://api.github.com/repos/shuxiong/phoenix/hooks","issue_events_url":"https://api.github.com/repos/shuxiong/phoenix/issues/events{/number}","events_url":"https://api.github.com/repos/shuxiong/phoenix/events","assignees_url":"https://api.github.com/repos/shuxiong/phoenix/assignees{/user}","branches_url":"https://api.github.com/repos/shuxiong/phoenix/branches{/branch}","tags_url":"https://api.github.com/repos/shuxiong/phoenix/tags","blobs_url":"https://api.github.com/repos/shuxiong/phoenix/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/shuxiong/phoenix/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/shuxiong/phoenix/git/refs{/sha}","trees_url":"https://api.github.com/repos/shuxiong/phoenix/git/trees{/sha}","statuses_url":"https://api.github.com/repos/shuxiong/phoenix/statuses/{sha}","languages_url":"https://api.github.com/repos/shuxiong/phoenix/languages","stargazers_url":"https://api.github.com/repos/shuxiong/phoenix/stargazers","contributors_url":"https://api.github.com/repos/shuxiong/phoenix/contributors","subscribers_url":"https://api.github.com/repos/shuxiong/phoenix/subscribers","subscription_url":"https://api.github.com/repos/shuxiong/phoenix/subscription","commits_url":"https://api.github.com/repos/shuxiong/phoenix/commits{/sha}","git_commits_url":"https://api.github.com/repos/shuxiong/phoenix/git/commits{/sha}","comments_url":"https://api.github.com/repos/shuxiong/phoenix/comments{/number}","issue_comment_url":"https://api.github.com/repos/shuxiong/phoenix/issues/comments{/number}","contents_url":"https://api.github.com/repos/shuxiong/phoenix/contents/{+path}","compare_url":"https://api.github.com/repos/shuxiong/phoenix/compare/{base}...{head}","merges_url":"https://api.github.com/repos/shuxiong/phoenix/merges","archive_url":"https://api.github.com/repos/shuxiong/phoenix/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/shuxiong/phoenix/downloads","issues_url":"https://api.github.com/repos/shuxiong/phoenix/issues{/number}","pulls_url":"https://api.github.com/repos/shuxiong/phoenix/pulls{/number}","milestones_url":"https://api.github.com/repos/shuxiong/phoenix/milestones{/number}","notifications_url":"https://api.github.com/repos/shuxiong/phoenix/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/shuxiong/phoenix/labels{/name}","releases_url":"https://api.github.com/repos/shuxiong/phoenix/releases{/id}","created_at":"2015-03-09T12:52:40Z","updated_at":"2015-03-09T12:52:44Z","pushed_at":"2015-03-17T01:20:06Z","git_url":"git://github.com/shuxiong/phoenix.git","ssh_url":"git@github.com:shuxiong/phoenix.git","clone_url":"https://github.com/shuxiong/phoenix.git","svn_url":"https://github.com/shuxiong/phoenix","homepage":null,"size":13164,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apache:4.3","ref":"4.3","sha":"84767cf6db99ae3f3ead8e2c358c2139a1fc7718","user":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":20473418,"name":"phoenix","full_name":"apache/phoenix","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars.githubusercontent.com/u/47359?v=3","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/phoenix","description":"Mirror of Apache Phoenix","fork":false,"url":"https://api.github.com/repos/apache/phoenix","forks_url":"https://api.github.com/repos/apache/phoenix/forks","keys_url":"https://api.github.com/repos/apache/phoenix/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/phoenix/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/phoenix/teams","hooks_url":"https://api.github.com/repos/apache/phoenix/hooks","issue_events_url":"https://api.github.com/repos/apache/phoenix/issues/events{/number}","events_url":"https://api.github.com/repos/apache/phoenix/events","assignees_url":"https://api.github.com/repos/apache/phoenix/assignees{/user}","branches_url":"https://api.github.com/repos/apache/phoenix/branches{/branch}","tags_url":"https://api.github.com/repos/apache/phoenix/tags","blobs_url":"https://api.github.com/repos/apache/phoenix/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/phoenix/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/phoenix/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/phoenix/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/phoenix/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/phoenix/languages","stargazers_url":"https://api.github.com/repos/apache/phoenix/stargazers","contributors_url":"https://api.github.com/repos/apache/phoenix/contributors","subscribers_url":"https://api.github.com/repos/apache/phoenix/subscribers","subscription_url":"https://api.github.com/repos/apache/phoenix/subscription","commits_url":"https://api.github.com/repos/apache/phoenix/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/phoenix/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/phoenix/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/phoenix/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/phoenix/contents/{+path}","compare_url":"https://api.github.com/repos/apache/phoenix/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/phoenix/merges","archive_url":"https://api.github.com/repos/apache/phoenix/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/phoenix/downloads","issues_url":"https://api.github.com/repos/apache/phoenix/issues{/number}","pulls_url":"https://api.github.com/repos/apache/phoenix/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/phoenix/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/phoenix/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/phoenix/labels{/name}","releases_url":"https://api.github.com/repos/apache/phoenix/releases{/id}","created_at":"2014-06-04T07:00:08Z","updated_at":"2015-03-18T05:16:29Z","pushed_at":"2015-03-18T04:52:06Z","git_url":"git://github.com/apache/phoenix.git","ssh_url":"git@github.com:apache/phoenix.git","clone_url":"https://github.com/apache/phoenix.git","svn_url":"https://github.com/apache/phoenix","homepage":null,"size":25162,"stargazers_count":49,"watchers_count":49,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":89,"mirror_url":"git://git.apache.org/phoenix.git","open_issues_count":29,"forks":89,"open_issues":29,"watchers":49,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/phoenix/pulls/46"},"html":{"href":"https://github.com/apache/phoenix/pull/46"},"issue":{"href":"https://api.github.com/repos/apache/phoenix/issues/46"},"comments":{"href":"https://api.github.com/repos/apache/phoenix/issues/46/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/phoenix/pulls/46/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/phoenix/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/phoenix/pulls/46/commits"},"statuses":{"href":"https://api.github.com/repos/apache/phoenix/statuses/740f53d0cdf28300bf94c0a197245874d58005da"}}}}