[#7538] set OnlyInt:true when a view column expression is loosely known to return int-only values
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
## v0.36.6 (WIP)
|
||||||
|
|
||||||
|
- Set `NumberField.OnlyInt:true` for the generated View collection schema fields when a view column expression is known to return int-only values ([#7538](https://github.com/pocketbase/pocketbase/issues/7538)).
|
||||||
|
|
||||||
|
|
||||||
## v0.36.5
|
## v0.36.5
|
||||||
|
|
||||||
- Disabled collection and fields name normalization while in IME mode ([#7532](https://github.com/pocketbase/pocketbase/pull/7532); thanks @miaopan607).
|
- Disabled collection and fields name normalization while in IME mode ([#7532](https://github.com/pocketbase/pocketbase/pull/7532); thanks @miaopan607).
|
||||||
|
|||||||
23
core/view.go
23
core/view.go
@@ -257,7 +257,16 @@ func parseQueryToFields(app App, selectQuery string) (map[string]*queryField, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// numeric aggregations
|
// numeric aggregations
|
||||||
if strings.HasPrefix(colLower, "count(") || strings.HasPrefix(colLower, "total(") {
|
if strings.HasPrefix(colLower, "count(") {
|
||||||
|
result[col.alias] = &queryField{
|
||||||
|
field: &NumberField{
|
||||||
|
Name: col.alias,
|
||||||
|
OnlyInt: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(colLower, "total(") {
|
||||||
result[col.alias] = &queryField{
|
result[col.alias] = &queryField{
|
||||||
field: &NumberField{
|
field: &NumberField{
|
||||||
Name: col.alias,
|
Name: col.alias,
|
||||||
@@ -268,16 +277,24 @@ func parseQueryToFields(app App, selectQuery string) (map[string]*queryField, er
|
|||||||
|
|
||||||
castMatch := castRegex.FindStringSubmatch(colLower)
|
castMatch := castRegex.FindStringSubmatch(colLower)
|
||||||
|
|
||||||
// numeric casts
|
// casts
|
||||||
if len(castMatch) == 2 {
|
if len(castMatch) == 2 {
|
||||||
switch castMatch[1] {
|
switch castMatch[1] {
|
||||||
case "real", "integer", "int", "decimal", "numeric":
|
case "real", "decimal", "numeric":
|
||||||
result[col.alias] = &queryField{
|
result[col.alias] = &queryField{
|
||||||
field: &NumberField{
|
field: &NumberField{
|
||||||
Name: col.alias,
|
Name: col.alias,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
case "int", "integer":
|
||||||
|
result[col.alias] = &queryField{
|
||||||
|
field: &NumberField{
|
||||||
|
Name: col.alias,
|
||||||
|
OnlyInt: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
continue
|
||||||
case "text":
|
case "text":
|
||||||
result[col.alias] = &queryField{
|
result[col.alias] = &queryField{
|
||||||
field: &TextField{
|
field: &TextField{
|
||||||
|
|||||||
@@ -545,6 +545,61 @@ func TestCreateViewFields(t *testing.T) {
|
|||||||
ensureNoTempViews(app, t)
|
ensureNoTempViews(app, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreateViewFieldsWithNumberOnlyInt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
app, _ := tests.NewTestApp()
|
||||||
|
defer app.Cleanup()
|
||||||
|
|
||||||
|
sql := `select
|
||||||
|
a.id,
|
||||||
|
count(a.id) count,
|
||||||
|
total(a.id) total,
|
||||||
|
cast(a.id as int) cast_int,
|
||||||
|
cast(a.id as integer) cast_integer,
|
||||||
|
cast(a.id as real) cast_real,
|
||||||
|
cast(a.id as decimal) cast_decimal,
|
||||||
|
cast(a.id as numeric) cast_numeric
|
||||||
|
from demo1 a`
|
||||||
|
|
||||||
|
result, err := app.CreateViewFields(sql)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
onlyInts := map[string]bool{
|
||||||
|
"count": true,
|
||||||
|
"total": false,
|
||||||
|
"cast_int": true,
|
||||||
|
"cast_integer": true,
|
||||||
|
"cast_real": false,
|
||||||
|
"cast_decimal": false,
|
||||||
|
"cast_numeric": false,
|
||||||
|
}
|
||||||
|
|
||||||
|
totalExpected := len(onlyInts) + 1
|
||||||
|
if total := len(result); total != totalExpected {
|
||||||
|
t.Fatalf("Expected %d, got %d", totalExpected, total)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range result {
|
||||||
|
if f.GetName() == "id" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run(f.GetName(), func(t *testing.T) {
|
||||||
|
nf, ok := f.(*core.NumberField)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Expected *core.NumberField, got %v", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nf.OnlyInt != onlyInts[nf.Name] {
|
||||||
|
t.Fatalf("Expected OnlyInt %v, got %v", onlyInts[nf.Name], nf.OnlyInt)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFindRecordByViewFile(t *testing.T) {
|
func TestFindRecordByViewFile(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user