200 lines · 4.2 KB · Go
RawDownload
// Copyright (c) 2015-2021 MinIO, Inc.//// This file is part of MinIO Object Storage stack//// This program is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with this program.  If not, see <http://www.gnu.org/licenses/>. package sql import (	"errors"	"strings") var (	errMalformedEscapeSequence  = errors.New("Malformed escape sequence in LIKE clause")	errInvalidTrimArg           = errors.New("Trim argument is invalid - this should not happen")	errInvalidSubstringIndexLen = errors.New("Substring start index or length falls outside the string")) const (	percent    rune = '%'	underscore rune = '_'	runeZero   rune = 0) func evalSQLLike(text, pattern string, escape rune) (match bool, err error) {	s := []rune{}	prev := runeZero	hasLeadingPercent := false	patLen := len([]rune(pattern))	for i, r := range pattern {		if i > 0 && prev == escape {			switch r {			case percent, escape, underscore:				s = append(s, r)				prev = r				if r == escape {					prev = runeZero				}			default:				return false, errMalformedEscapeSequence			}			continue		} 		prev = r 		var ok bool		switch r {		case percent:			if len(s) == 0 {				hasLeadingPercent = true				continue			} 			text, ok = matcher(text, string(s), hasLeadingPercent)			if !ok {				return false, nil			}			hasLeadingPercent = true			s = []rune{} 			if i == patLen-1 {				// Last pattern character is a %, so				// we are done.				return true, nil			} 		case underscore:			if len(s) == 0 {				text, ok = dropRune(text)				if !ok {					return false, nil				}				continue			} 			text, ok = matcher(text, string(s), hasLeadingPercent)			if !ok {				return false, nil			}			hasLeadingPercent = false 			text, ok = dropRune(text)			if !ok {				return false, nil			}			s = []rune{} 		case escape:			if i == patLen-1 {				return false, errMalformedEscapeSequence			}			// Otherwise do nothing. 		default:			s = append(s, r)		} 	}	if hasLeadingPercent {		return strings.HasSuffix(text, string(s)), nil	}	return string(s) == text, nil} // matcher - Finds `pat` in `text`, and returns the part remainder of// `text`, after the match. If leadingPercent is false, `pat` must be// the prefix of `text`, otherwise it must be a substring.func matcher(text, pat string, leadingPercent bool) (res string, match bool) {	if !leadingPercent {		res = strings.TrimPrefix(text, pat)		if len(text) == len(res) {			return "", false		}	} else {		parts := strings.SplitN(text, pat, 2)		if len(parts) == 1 {			return "", false		}		res = parts[1]	}	return res, true} func dropRune(text string) (res string, ok bool) {	r := []rune(text)	if len(r) == 0 {		return "", false	}	return string(r[1:]), true} func evalSQLSubstring(s string, startIdx, length int) (res string, err error) {	rs := []rune(s) 	// According to s3 document, if startIdx < 1, it is set to 1.	if startIdx < 1 {		startIdx = 1	} 	if startIdx > len(rs) {		startIdx = len(rs) + 1	} 	// StartIdx is 1-based in the input	startIdx--	endIdx := len(rs)	if length != -1 {		if length < 0 {			return "", errInvalidSubstringIndexLen		} 		if length > (endIdx - startIdx) {			length = endIdx - startIdx		} 		endIdx = startIdx + length	} 	return string(rs[startIdx:endIdx]), nil} const (	trimLeading  = "LEADING"	trimTrailing = "TRAILING"	trimBoth     = "BOTH") func evalSQLTrim(where *string, trimChars, text string) (result string, err error) {	cutSet := " "	if trimChars != "" {		cutSet = trimChars	} 	trimFunc := strings.Trim	switch {	case where == nil:	case *where == trimBoth:	case *where == trimLeading:		trimFunc = strings.TrimLeft	case *where == trimTrailing:		trimFunc = strings.TrimRight	default:		return "", errInvalidTrimArg	} 	return trimFunc(text, cutSet), nil}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t