* add ability to use Θ in all field names & with PQL
This commit is contained in:
Jacob Brinlee 2023-02-22 11:30:14 -06:00 committed by GitHub
parent 26747362e1
commit df7e813f01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 1138 additions and 1041 deletions

View file

@ -32,7 +32,7 @@ const (
var (
ErrNoFieldSpec = errors.New("no field spec in this header")
ErrInvalidFieldName = errors.New("field name must match [a-z][a-z0-9_-]{0,229}")
ErrInvalidFieldName = errors.New("field name must match [a-z][a-z0-9Θ_-]{0,229}")
ErrParsingEpoch = "parsing epoch for "
ErrDecodingConfig = "decoding config for field "
)

View file

@ -351,6 +351,11 @@ func TestHeaderToField(t *testing.T) {
input: "a__LookupText",
exp: LookupTextField{NameVal: "a", DestNameVal: "a"},
},
{
name: "theta",
input: "fldΘnameΘ__String",
exp: StringField{NameVal: "fldΘnameΘ", DestNameVal: "fldΘnameΘ"},
},
}
for _, test := range tests {

View file

@ -47,7 +47,7 @@ var (
ErrInvalidView = errors.New("invalid view")
ErrInvalidCacheType = errors.New("invalid cache type")
ErrName = errors.New("invalid index or field name, must match [a-z][a-z0-9_-]* and contain at most 230 characters")
ErrName = errors.New("invalid index or field name, must match [a-z][a-z0-9Θ_-]* and contain at most 230 characters")
// ErrFragmentNotFound is returned when a fragment does not exist.
ErrFragmentNotFound = errors.New("fragment not found")
@ -135,7 +135,7 @@ func newPreconditionFailedError(err error) PreconditionFailedError {
}
// Regular expression to validate index and field names.
var nameRegexp = regexp.MustCompile(`^[a-z][a-z0-9_-]{0,229}$`)
var nameRegexp = regexp.MustCompile(`^[a-z][a-z0-9Θ_-]{0,229}$`)
// TimeFormat is the go-style time format used to parse string dates.
const TimeFormat = "2006-01-02T15:04"

View file

@ -3,6 +3,7 @@
package pilosa_test
import (
"fmt"
"strings"
"testing"
@ -43,3 +44,28 @@ func TestAddressWithDefaults(t *testing.T) {
}
}
}
func TestValidateName(t *testing.T) {
tests := []struct {
name string
err error
}{
{name: "a_name", err: nil},
{name: "a-name", err: nil},
{name: "a-name-10", err: nil},
{name: "A-name", err: fmt.Errorf("'A-name': %s", pilosa.ErrName)},
{name: "-a-name", err: fmt.Errorf("'-a-name': %s", pilosa.ErrName)},
{name: "8th_name", err: fmt.Errorf("'8th_name': %s", pilosa.ErrName)},
{name: "Θ_name", err: fmt.Errorf("'Θ_name': %s", pilosa.ErrName)},
{name: "a_NaMe", err: fmt.Errorf("'a_NaMe': %s", pilosa.ErrName)},
{name: "indexΘname", err: nil},
}
for _, test := range tests {
err := pilosa.ValidateName(test.name)
if !(err == nil && test.err == nil) {
if err.Error() != test.err.Error() {
t.Errorf("expected error: %v, but got: %v", test.err, err)
}
}
}
}

View file

@ -307,6 +307,20 @@ func TestParser_Parse(t *testing.T) {
}
}
})
t.Run("ParseTheta", func(t *testing.T) {
q, err := pql.ParseString(`Row(fldΘname=fldΘval)`)
if err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(q.Calls[0],
&pql.Call{
Name: "Row",
Args: map[string]interface{}{"fldΘname": "fldΘval"},
},
) {
t.Fatalf("unexpected call: %#v", q.Calls[0])
}
})
}
func TestUnquote(t *testing.T) {

View file

@ -20,7 +20,7 @@ Call <- "Set" {p.startCall("Set")} open col comma args (comma time)? close {p.e
/ "Sum" {p.startCall("Sum")} open posfield (comma allargs)? close {p.endCall()}
/ "Range" {p.startCall("Range")} open field eq value comma 'from='? {p.addField("from")} timefmt {p.addVal(text)} comma 'to='? sp {p.addField("to")} timefmt {p.addVal(text)} close {p.endCall()}
/ < IDENT > { p.startCall(text) } open allargs comma? close { p.endCall() }
ivyExpr <- ( '(' / '_' / '/' / '[' / ']' /'.' / '=' / '&' / '<'/ '>' /',' / ')' / '^' / '!' / '|' / [*+] / '-' / '?' / [[A-Z]] / [0-9] / '#' / [ \t\n] )*
ivyExpr <- ( '(' / '_' / '/' / '[' / ']' /'.' / '=' / '&' / '<'/ '>' /',' / ')' / '^' / '!' / '|' / [*+] / '-' / '?' / [[A-Z]] / [0-9] / '#' / [ \t\n] / 'Θ')*
ivyprogram <- '"'? <ivyExpr> '"' { p.addPosStr("_ivy", text) }
ivyprogram2 <- '"'? <ivyExpr> '"' { p.addPosStr("_ivyReduce", text) }
@ -55,16 +55,16 @@ item <- 'null' &(comma / close) { p.addVal(nil) }
/ timestampfmt { p.addTimestampVal(text) }
/ < decimal > { p.addNumVal(text) }
/ < IDENT > { p.startCall(text) } open allargs comma? close { p.addVal(p.endCall()) }
/ < ([[A-Z]] / [0-9] / '-' / '_' / ':')+ > { p.addVal(text) }
/ < ([[A-Z]] / [0-9] / '-' / '_' / ':' / 'Θ')+ > { p.addVal(text) }
/ < '"' doublequotedstring '"' > { p.addVal(text) }
/ < '\'' singlequotedstring '\'' > { p.addVal(text) }
doublequotedstring <- ( '\\"' / '\\\\' / '\\n' / '\\t' / [^"\\] )*
singlequotedstring <- ( '\\\'' / '\\\\' / '\\n' / '\\t' / [^'\\] )*
variable <- ( [[A-Z]] / '_' ) ( [[A-Z]] / [0-9] / '_' / '-' )*
variable <- ( [[A-Z]] / '_' ) ( [[A-Z]] / [0-9] / '_' / '-' / 'Θ')*
fieldExpr <- ( [[A-Z]] / '_' / '$' ) ( [[A-Z]] / [0-9] / '_' / '-' )*
fieldExpr <- ( [[A-Z]] / '_' / '$' ) ( [[A-Z]] / [0-9] / '_' / '-' / 'Θ')*
field <- <fieldExpr / reserved> { p.addField(text) }
reserved <- '_row' / '_col' / '_start' / '_end' / '_timestamp' / '_field'
posfield <- 'field='? <fieldExpr> { p.addPosStr("_field", text) }
@ -79,7 +79,7 @@ eq <- sp '=' sp
comma <- sp ',' sp
lbrack <- '[' sp
rbrack <- sp ']' sp
IDENT <- [[A-Z]] ([[A-Z]] / [0-9])*
IDENT <- [[A-Z]] ([[A-Z]] / [0-9] / 'Θ')*
digits <- [0-9]+
signedDigits <- '-'? digits
decimal <- signedDigits ('.' digits?)?

File diff suppressed because it is too large Load diff

View file

@ -353,7 +353,7 @@ func TestPQLDeepEquality(t *testing.T) {
},
}},
{
name: "RowWithUnicode",
name: "RowValWithUnicode",
call: `Row(unicode="Æ漢д ☮♬ ♞🜻💣")`,
exp: &Call{
Name: "Row",
@ -361,6 +361,15 @@ func TestPQLDeepEquality(t *testing.T) {
"unicode": `Æ漢д ☮♬ ♞🜻💣`,
},
}},
{
name: "RowWithUnicode",
call: `Row(uniΘcode="Æ漢д ☮♬ ♞🜻💣")`,
exp: &Call{
Name: "Row",
Args: map[string]interface{}{
"uniΘcode": `Æ漢д ☮♬ ♞🜻💣`,
},
}},
{
name: "RowsWithUnicode",
call: `Rows(job, previous="💣")`,