Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: "char" is supposed to truncate long values #66422

Merged
merged 1 commit into from
Jun 21, 2021

Conversation

alxfv
Copy link
Contributor

@alxfv alxfv commented Jun 14, 2021

Resolves #65631

Release note (sql change, backward-incompatible change): The "char"
column type will truncate long values in line with Postgres.

@cockroach-teamcity
Copy link
Member

cockroach-teamcity commented Jun 14, 2021

CLA assistant check
All committers have signed the CLA.

@blathers-crl
Copy link

blathers-crl bot commented Jun 14, 2021

Thank you for contributing to CockroachDB. Please ensure you have followed the guidelines for creating a PR.

Before a member of our team reviews your PR, I have some potential action items for you:

  • Please ensure your git commit message contains a release note.
  • When CI has completed, please ensure no errors have appeared.

I have added a few people who may be able to assist in reviewing:

🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is otan.

@blathers-crl blathers-crl bot added O-community Originated from the community X-blathers-triaged blathers was able to find an owner labels Jun 14, 2021
@blathers-crl blathers-crl bot requested a review from rafiss June 14, 2021 11:47
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@alxfv alxfv changed the title [wip] sql: "char" is supposed to truncate long values sql: "char" is supposed to truncate long values Jun 14, 2021
@rafiss rafiss requested a review from a team June 14, 2021 16:37
Copy link
Contributor

@otan otan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! one small improvement

@@ -434,6 +436,12 @@ func AdjustValueToType(typ *types.T, inVal Datum) (outVal Datum, err error) {
} else if _, ok := inVal.(*DCollatedString); ok {
return NewDCollatedString(strings.TrimRight(sv, " "), typ.Locale(), &CollationEnvironment{})
}
} else if typ.Oid() == oid.T_char {
if _, ok := AsDString(inVal); ok {
return NewDString(util.TruncateString(sv, 1)), nil
Copy link
Contributor

@otan otan Jun 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have to TruncateString again here?
i think we can omit the second usage of TrimRight above as well - oops.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, good catch

@@ -578,6 +584,11 @@ func (expr *StrVal) ResolveAsType(
expr.resString = DString(strings.TrimRight(expr.s, " "))
return &expr.resString, nil
}
// "char" is supposed to truncate long values
if typ.Oid() == oid.T_char {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this logic is very similar to above and the code in AdjustValueToType.

Do you mind making a routine

func adjustStringToType(typ *types.T, str string) string {
   switch typ.Oid() {
      case oid.T_char:
         // ...
      case oid.T_bpchar:
         // ...
   }
   return str
}

and using it in all three places, replacing the TrimRight && TruncateString code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@alxfv alxfv force-pushed the char-truncate-long-values-65631 branch from 2fc0bc6 to d143764 Compare June 15, 2021 18:28
@blathers-crl blathers-crl bot requested a review from otan June 15, 2021 18:28
@blathers-crl
Copy link

blathers-crl bot commented Jun 15, 2021

Thank you for updating your pull request.

My owl senses detect your PR is good for review. Please keep an eye out for any test failures in CI.

🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is otan.

Copy link
Contributor

@otan otan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

bors r+

@craig
Copy link
Contributor

craig bot commented Jun 15, 2021

Build failed (retrying...):

@craig
Copy link
Contributor

craig bot commented Jun 15, 2021

Build failed:

@alxfv alxfv force-pushed the char-truncate-long-values-65631 branch from d143764 to 8070c62 Compare June 16, 2021 07:46
@rafiss
Copy link
Collaborator

rafiss commented Jun 16, 2021

hmm seems like this is causing issues because of how we type CASE expressions (pkg/sql/opt/memo/typing.go):

// typeCase returns the type of a CASE expression, which is
// of the form:
//   CASE [ <cond> ]
//       WHEN <condval1> THEN <expr1>
//     [ WHEN <condval2> THEN <expr2> ] ...
//     [ ELSE <expr> ]
//   END
// The type is equal to the type of the WHEN <condval> THEN <expr> clauses, or
// the type of the ELSE <expr> value if all the previous types are unknown.
func typeCase(e opt.ScalarExpr) *types.T {
	caseExpr := e.(*CaseExpr)
	return InferWhensType(caseExpr.Whens, caseExpr.OrElse)
}

so a CASE where the inputs are all "char" is automatically assumed to output "char". But that's not really what we want here, for one example:

func (d *delegator) delegateShowConstraints(n *tree.ShowConstraints) (tree.Statement, error) {
sqltelemetry.IncrementShowCounter(sqltelemetry.Constraints)
const getConstraintsQuery = `
SELECT
t.relname AS table_name,
c.conname AS constraint_name,
CASE c.contype
WHEN 'p' THEN 'PRIMARY KEY'
WHEN 'u' THEN 'UNIQUE'
WHEN 'c' THEN 'CHECK'
WHEN 'f' THEN 'FOREIGN KEY'
ELSE c.contype

@otan any idea if it's safe to change that case typing rule?

@otan otan self-requested a review June 16, 2021 21:58
@otan
Copy link
Contributor

otan commented Jun 16, 2021

ah that's super gross :(

we really should be asserting that all the THEN clauses have the same type.

i think for now the safest thing to do is change the CASE to CASE c.contype::text

Release note (sql change, backward-incompatible change): The "char"
column type will truncate long values in line with Postgres.
@alxfv alxfv force-pushed the char-truncate-long-values-65631 branch from 8070c62 to 3309914 Compare June 21, 2021 10:20
@alxfv
Copy link
Contributor Author

alxfv commented Jun 21, 2021

ah that's super gross :(

we really should be asserting that all the THEN clauses have the same type.

i think for now the safest thing to do is change the CASE to CASE c.contype::text

CASE c.contetype::text didn't work, so I checked:

func InferWhensType(whens ScalarListExpr, orElse opt.ScalarExpr) *types.T {
result := orElse.DataType()
// Sanity check.
for _, when := range whens {
if !result.Equivalent(when.DataType()) {
panic(errors.AssertionFailedf("inconsistent Case return types %s %s", when.DataType(), result))
}
}
return result
}

casting ELSE is enough:

CASE c.contype
WHEN 'p' THEN 'PRIMARY KEY'
WHEN 'u' THEN 'UNIQUE'
WHEN 'c' THEN 'CHECK'
WHEN 'f' THEN 'FOREIGN KEY'
ELSE c.contype::TEXT
END AS constraint_type,

Copy link
Contributor

@otan otan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice. lgtm!

bors r+

@craig
Copy link
Contributor

craig bot commented Jun 21, 2021

Build succeeded:

@craig craig bot merged commit 88cc7c8 into cockroachdb:master Jun 21, 2021
@alxfv alxfv deleted the char-truncate-long-values-65631 branch June 22, 2021 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-community Originated from the community X-blathers-triaged blathers was able to find an owner
Projects
None yet
Development

Successfully merging this pull request may close these issues.

sql: "char" is supposed to truncate long values
4 participants