Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion core/typecollection/typecollection.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (

"github.com/dolthub/doltgresql/core/id"
"github.com/dolthub/doltgresql/core/rootobject/objinterface"
"github.com/dolthub/doltgresql/postgres/parser/pgcode"
"github.com/dolthub/doltgresql/postgres/parser/pgerror"
parsertypes "github.com/dolthub/doltgresql/postgres/parser/types"
pgtypes "github.com/dolthub/doltgresql/server/types"
)
Expand Down Expand Up @@ -240,7 +242,7 @@ func (pgs *TypeCollection) ResolveType(ctx context.Context, name id.Type) (*pgty
return nil, err
}
if !t.IsResolvedType() {
return nil, errors.Errorf("unable to resolve type `%s`", name.TypeName())
return nil, pgerror.WithCandidateCode(errors.Errorf("unable to resolve type `%s`", name.TypeName()), pgcode.UndefinedObject)
}
return t, nil
}
Expand Down
3 changes: 1 addition & 2 deletions server/cast/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@ import (
"unicode/utf8"

cerrors "github.com/cockroachdb/errors"
"gopkg.in/src-d/go-errors.v1"

pgtypes "github.com/dolthub/doltgresql/server/types"
)

// errOutOfRange is returned when a value is out of range for a given type.
var errOutOfRange = errors.NewKind("%s out of range")
var errOutOfRange = pgtypes.ErrOutOfRange

// handleStringCast handles casts to the string types that may have length restrictions. Returns an error if other types
// are passed in. Will always return the correct string, even on error, as some contexts may ignore the error.
Expand Down
118 changes: 95 additions & 23 deletions server/connection_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ import (
"github.com/dolthub/doltgresql/postgres/parser/parser"
psql "github.com/dolthub/doltgresql/postgres/parser/parser/sql"
"github.com/dolthub/doltgresql/postgres/parser/pgcode"
"github.com/dolthub/doltgresql/postgres/parser/pgerror"
"github.com/dolthub/doltgresql/postgres/parser/sem/tree"
"github.com/dolthub/doltgresql/server/ast"
"github.com/dolthub/doltgresql/server/functions/framework"
"github.com/dolthub/doltgresql/server/node"
pgtypes "github.com/dolthub/doltgresql/server/types"
)

// ConnectionHandler is responsible for the entire lifecycle of a user connection: receiving messages they send,
Expand Down Expand Up @@ -1426,21 +1429,11 @@ func (h *ConnectionHandler) endOfMessages(err error) {

// sendError sends the given error to the client. This should generally never be called directly.
func (h *ConnectionHandler) sendError(err error) {
var severity, code, errMsg string
if pgErr, ok := err.(*pgconn.PgError); ok {
severity = pgErr.Severity
code = pgErr.Code
errMsg = pgErr.Message
} else {
severity = string(ErrorResponseSeverity_Error)
code = pgcode.Internal.String() // internal_error for now
errMsg = err.Error()
}
fmt.Println(errMsg)
pgErr := castSQLError(err)
if sendErr := h.send(&pgproto3.ErrorResponse{
Severity: severity,
Code: code,
Message: errMsg,
Severity: pgErr.Severity,
Code: pgErr.Code,
Message: pgErr.Message,
}); sendErr != nil {
// If we're unable to send anything to the connection, then there's something wrong with the connection and
// we should terminate it. This will be caught in HandleConnection's defer block.
Expand Down Expand Up @@ -1584,12 +1577,68 @@ func castSQLError(err error) *pgconn.PgError {
return castSQLError(wm.Err)
}

// TODO: map more errors case
// Errors originating in our Postgres-derived parser already carry a candidate SQLSTATE (e.g. 42601
// for syntax errors, 0A000 for unimplemented syntax); report that code directly when present.
if pgerror.HasCandidateCode(err) {
if code := pgerror.GetPGCode(err); code != pgcode.Uncategorized {
return &pgconn.PgError{
Severity: string(ErrorResponseSeverity_Error),
Code: code.String(),
Message: err.Error(),
}
}
}

// Errors that reach a client with an XX-class (internal error) code are more than cosmetic: some
// clients (e.g. Npgsql) treat XX-class errors as critical failures and close the connection, so any
// error a client can provoke should be mapped to its proper SQLSTATE here.
// TODO: should update the error message to match Postgres
var code pgcode.Code
switch {
case sql.ErrCheckConstraintViolated.Is(err):
// Class 0A — Feature Not Supported
case sql.ErrUnsupportedFeature.Is(err), sql.ErrUnsupportedSyntax.Is(err):
code = pgcode.FeatureNotSupported
// Class 21 — Cardinality Violation
case sql.ErrExpectedSingleRow.Is(err), sql.ErrMoreThanOneRow.Is(err):
code = pgcode.CardinalityViolation
// Class 22 — Data Exception
case pgtypes.ErrDivisionByZero.Is(err):
code = pgcode.DivisionByZero
case sql.ErrValueOutOfRange.Is(err), pgtypes.ErrValueIsOutOfRangeForType.Is(err),
pgtypes.ErrOutOfRange.Is(err), pgtypes.ErrInputOutOfRange.Is(err),
errors.Is(err, pgtypes.ErrCastOutOfRange):
code = pgcode.NumericValueOutOfRange
case pgtypes.ErrInvalidSyntaxForType.Is(err), sql.ErrInvalidValue.Is(err):
code = pgcode.InvalidTextRepresentation
case pgtypes.ErrWrongLengthBit.Is(err), pgtypes.ErrVarBitLengthExceeded.Is(err):
code = pgcode.StringDataLengthMismatch
case sql.ErrInvalidTimeZone.Is(err), sql.ErrInvalidArgument.Is(err), sql.ErrInvalidArgumentDetails.Is(err):
code = pgcode.InvalidParameterValue
// Class 23 — Integrity Constraint Violation
case sql.ErrPrimaryKeyViolation.Is(err), sql.ErrUniqueKeyViolation.Is(err),
sql.ErrDuplicateEntry.Is(err), sql.ErrDuplicateEntrySet.Is(err):
code = pgcode.UniqueViolation
case sql.ErrForeignKeyChildViolation.Is(err), sql.ErrForeignKeyParentViolation.Is(err),
sql.ErrForeignKeyNotResolved.Is(err):
code = pgcode.ForeignKeyViolation
case sql.ErrCheckConstraintViolated.Is(err), pgtypes.ErrDomainValueViolatesCheckConstraint.Is(err):
code = pgcode.CheckViolation
case sql.ErrInsertIntoNonNullableProvidedNull.Is(err), sql.ErrInsertIntoNonNullableDefaultNullColumn.Is(err),
sql.ErrColumnDefaultReturnedNull.Is(err), pgtypes.ErrDomainDoesNotAllowNullValues.Is(err):
code = pgcode.NotNullViolation
// Class 25 — Invalid Transaction State
case sql.ErrReadOnly.Is(err), sql.ErrReadOnlyTransaction.Is(err):
code = pgcode.ReadOnlySQLTransaction
// Classes 26, 34, 3B — statement, cursor, and savepoint names
case sql.ErrUnknownPreparedStatement.Is(err):
code = pgcode.InvalidSQLStatementName
case sql.ErrCursorNotFound.Is(err):
code = pgcode.InvalidCursorName
case sql.ErrCursorAlreadyOpen.Is(err):
code = pgcode.DuplicateCursor
case sql.ErrSavepointDoesNotExist.Is(err):
code = pgcode.InvalidSavepointSpecification
// Classes 3D, 3F — catalog and schema names
case sql.ErrDatabaseExists.Is(err):
code = pgcode.DuplicateDatabase
case sql.ErrDatabaseNotFound.Is(err):
Expand All @@ -1598,14 +1647,37 @@ func castSQLError(err error) *pgconn.PgError {
code = pgcode.DuplicateSchema
case sql.ErrDatabaseSchemaNotFound.Is(err):
code = pgcode.UndefinedSchema
case sql.ErrForeignKeyChildViolation.Is(err):
code = pgcode.ForeignKeyViolation
case sql.ErrForeignKeyDuplicateName.Is(err):
code = pgcode.DuplicateObject
case sql.ErrTableNotFound.Is(err):
// Class 40 — Transaction Rollback. Dolt reports commit-time transaction conflicts as ErrLockDeadlock.
case sql.ErrLockDeadlock.Is(err):
code = pgcode.SerializationFailure
// Class 42 — Syntax or Access Rule Violation
case sql.ErrSyntaxError.Is(err), sql.ErrInvalidSyntax.Is(err), sql.ErrColValCountMismatch.Is(err),
sql.ErrInsertIntoMismatchValueCount.Is(err), sql.ErrColumnNumberDoesNotMatch.Is(err):
code = pgcode.Syntax
case sql.ErrPrivilegeCheckFailed.Is(err), sql.ErrDatabaseAccessDeniedForUser.Is(err),
sql.ErrTableAccessDeniedForUser.Is(err):
code = pgcode.InsufficientPrivilege
case sql.ErrNonAggregatedColumnWithoutGroupBy.Is(err):
code = pgcode.Grouping
case sql.ErrTableNotFound.Is(err), sql.ErrUnknownTable.Is(err), sql.ErrViewDoesNotExist.Is(err):
code = pgcode.UndefinedTable
case sql.ErrUniqueKeyViolation.Is(err):
code = pgcode.UniqueViolation
case sql.ErrTableAlreadyExists.Is(err), sql.ErrExistingView.Is(err):
code = pgcode.DuplicateRelation
case sql.ErrColumnNotFound.Is(err), sql.ErrTableColumnNotFound.Is(err), sql.ErrUnknownColumn.Is(err),
sql.ErrKeyColumnDoesNotExist.Is(err):
code = pgcode.UndefinedColumn
case sql.ErrColumnExists.Is(err), sql.ErrDuplicateColumn.Is(err), sql.ErrColumnSpecifiedTwice.Is(err):
code = pgcode.DuplicateColumn
case sql.ErrAmbiguousColumnName.Is(err), sql.ErrAmbiguousColumnOrAliasName.Is(err),
sql.ErrAmbiguousColumnInOrderBy.Is(err):
code = pgcode.AmbiguousColumn
case sql.ErrFunctionNotFound.Is(err), sql.ErrTableFunctionNotFound.Is(err),
sql.ErrInvalidArgumentNumber.Is(err), framework.ErrFunctionDoesNotExist.Is(err):
code = pgcode.UndefinedFunction
case sql.ErrForeignKeyDuplicateName.Is(err), pgtypes.ErrTypeAlreadyExists.Is(err):
code = pgcode.DuplicateObject
case sql.ErrUnknownSystemVariable.Is(err), sql.ErrUnknownConstraint.Is(err), pgtypes.ErrTypeDoesNotExist.Is(err):
code = pgcode.UndefinedObject
default:
code = pgcode.Internal
}
Expand Down
3 changes: 1 addition & 2 deletions server/functions/acos.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var acos_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Acos(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return r, nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/acosd.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var acosd_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Acos(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return toDegrees(r), nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/acosh.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var acosh_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Acosh(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return r, nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/asin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var asin_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Asin(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return r, nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/asind.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var asind_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Asin(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return toDegrees(r), nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/asinh.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var asinh_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Asinh(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return r, nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/atan.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var atan_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Atan(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return r, nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/atan2.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var atan2_float64 = framework.Function2{
Callable: func(ctx *sql.Context, _ [3]*pgtypes.DoltgresType, y any, x any) (any, error) {
r := math.Atan2(y.(float64), x.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return r, nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/atan2d.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var atan2d_float64 = framework.Function2{
Callable: func(ctx *sql.Context, _ [3]*pgtypes.DoltgresType, y any, x any) (any, error) {
r := math.Atan2(y.(float64), x.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return toDegrees(r), nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/atand.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var atand_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Atan(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return toDegrees(r), nil
},
Expand Down
3 changes: 1 addition & 2 deletions server/functions/atanh.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package functions
import (
"math"

"github.com/cockroachdb/errors"
"github.com/dolthub/go-mysql-server/sql"

"github.com/dolthub/doltgresql/server/functions/framework"
Expand All @@ -38,7 +37,7 @@ var atanh_float64 = framework.Function1{
Callable: func(ctx *sql.Context, _ [2]*pgtypes.DoltgresType, val1 any) (any, error) {
r := math.Atanh(val1.(float64))
if math.IsNaN(r) {
return nil, errors.Errorf("input is out of range")
return nil, pgtypes.ErrInputOutOfRange.New()
}
return r, nil
},
Expand Down
Loading
Loading