From bb65eae4c70e29c74b6022e750cd6f3f6dc57d8c Mon Sep 17 00:00:00 2001 From: Ilya Sevostyanov <1166655+i-sevostyanov@users.noreply.github.com> Date: Tue, 6 Aug 2024 20:57:36 +0400 Subject: [PATCH] chore: update golangci-lint config and fix related issues --- .golangci.yml | 1961 +++++++++++++++-- cmd/shell/main.go | 1 + internal/shell/shell.go | 2 + internal/sql/engine/engine_test.go | 8 +- internal/sql/expr/binary_test.go | 5 +- internal/sql/expr/column.go | 3 +- internal/sql/expr/expression.go | 3 +- internal/sql/expr/logical/and.go | 12 +- internal/sql/expr/logical/or.go | 12 +- internal/sql/expr/math/add.go | 4 + internal/sql/expr/math/div.go | 10 +- internal/sql/expr/math/mod.go | 10 +- internal/sql/expr/math/mul.go | 3 + internal/sql/expr/math/pow.go | 3 + internal/sql/expr/math/sub.go | 3 + internal/sql/expr/math/unary_minus.go | 2 + internal/sql/expr/math/unary_plus.go | 2 + internal/sql/expr/unary_test.go | 4 +- internal/sql/parsing/ast/ast.go | 2 +- internal/sql/parsing/lexer/lexer.go | 3 + internal/sql/parsing/parser/parser.go | 21 +- internal/sql/planning/plan/create_test.go | 6 +- internal/sql/planning/plan/delete_test.go | 8 +- internal/sql/planning/plan/drop_test.go | 6 +- internal/sql/planning/plan/filter_test.go | 8 +- internal/sql/planning/plan/insert_test.go | 4 +- internal/sql/planning/plan/limit_test.go | 6 +- internal/sql/planning/plan/offset_test.go | 8 +- internal/sql/planning/plan/project_test.go | 8 +- internal/sql/planning/plan/scan_test.go | 4 +- internal/sql/planning/plan/sort.go | 1 + internal/sql/planning/plan/sort_test.go | 6 +- internal/sql/planning/plan/update_test.go | 10 +- internal/sql/planning/planner/planner.go | 27 +- internal/sql/planning/planner/planner_test.go | 28 +- internal/sql/rows.go | 1 + internal/storage/memory/catalog.go | 1 + internal/storage/memory/database.go | 5 +- internal/storage/memory/table.go | 3 + 39 files changed, 1904 insertions(+), 310 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a6704a3..5e6bfff 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,22 +1,28 @@ -# options for analysis running +# Options for analysis running. run: - # default concurrency is an available CPU number + # Number of operating system threads (`GOMAXPROCS`) that can execute golangci-lint simultaneously. + # If it is explicitly set to 0 (i.e., not the default) + # then golangci-lint will automatically set the value to match Linux container CPU quota. + # Default: the number of logical CPUs in the machine concurrency: 4 - # timeout for analysis, e.g., 30s, 5m, default is 1m + # Timeout for analysis, e.g. 30s, 5m. + # Default: 1m timeout: 5m - # exit code when at least one issue was found, default is 1 + # Exit code when at least one issue was found. + # Default: 1 issues-exit-code: 1 - # include test files or not, default is true + # Include test files or not. + # Default: true tests: true - # List of build tags, all linters use it. Default is empty list. - build-tags: [ ] + # List of build tags, all linters use it. + # Default: [] + build-tags: [] - # By default, isn't set. If set we pass it to "go list -mod={option}". - # From "go help modules": + # If set, we pass it to "go list -mod={option}". From "go help modules": # If invoked with -mod=readonly, the go command is disallowed from the implicit # automatic updating of go.mod described above. Instead, it fails when any changes # to go.mod are needed. This setting is most useful to check that go.mod does @@ -24,142 +30,1529 @@ run: # If invoked with -mod=vendor, the go command assumes that the vendor # directory holds the correct copies of dependencies and ignores # the dependency descriptions in go.mod. + # + # Allowed values: readonly|vendor|mod + # Default: "" modules-download-mode: readonly # Allow multiple parallel golangci-lint instances running. - # If false (default) - golangci-lint acquires file lock on start. + # If false, golangci-lint acquires file lock on start. + # Default: false allow-parallel-runners: false + # Allow multiple golangci-lint instances running, but serialize them around a lock. + # If false, golangci-lint exits with an error if it fails to acquire file lock on start. + # Default: false + allow-serial-runners: false + + # Define the Go version limit. + # Mainly related to generics support since go1.18. + # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 + # go: '1.19' + + # output configuration options output: - # colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions - # default is "colored-line-number" + # The formats used to render issues. + # Formats: + # - `colored-line-number` + # - `line-number` + # - `json` + # - `colored-tab` + # - `tab` + # - `html` + # - `checkstyle` + # - `code-climate` + # - `junit-xml` + # - `github-actions` + # - `teamcity` + # - `sarif` + # Output path can be either `stdout`, `stderr` or path to the file to write to. + # + # For the CLI flag (`--out-format`), multiple formats can be specified by separating them by comma. + # The output can be specified for each of them by separating format name and path by colon symbol. + # Example: "--out-format=checkstyle:report.xml,json:stdout,colored-line-number" + # The CLI flag (`--out-format`) override the configuration file. + # + # Default: + # formats: + # - format: colored-line-number + # path: stdout formats: - - format: colored-line-number - path: stdout + - format: colored-tab + path: stdout - # print lines of code with issue, default is true + # Print lines of code with issue. + # Default: true print-issued-lines: true - # print linter name at the end of issue text, default is true + # Print linter name at the end of issue text. + # Default: true print-linter-name: true - # make issues output unique by line, default is true + # Make issues output unique by line. + # Default: true uniq-by-line: true - # add a prefix to the output file references; default is no prefix + # Add a prefix to the output file references. + # Default: "" path-prefix: "" - # sorts results by: filepath, line and column + # Sort results by the order defined in `sort-order`. + # Default: false sort-results: true + # Order to use when sorting results. + # Require `sort-results` to `true`. + # Possible values: `file`, `linter`, and `severity`. + # + # If the severity values are inside the following list, they are ordered in this order: + # 1. error + # 2. warning + # 3. high + # 4. medium + # 5. low + # Either they are sorted alphabetically. + # + # Default: ["file"] + sort-order: + - linter + - severity + - file # filepath, line, and column. -# all available settings of specific linters + # Show statistics per linter. + # Default: false + show-stats: true + + +# All available settings of specific linters. linters-settings: + asasalint: + # To specify a set of function names to exclude. + # The values are merged with the builtin exclusions. + # The builtin exclusions can be disabled by setting `use-builtin-exclusions` to `false`. + # Default: ["^(fmt|log|logger|t|)\.(Print|Fprint|Sprint|Fatal|Panic|Error|Warn|Warning|Info|Debug|Log)(|f|ln)$"] + # exclude: + # - Append + # - \.Wrapf + # To enable/disable the asasalint builtin exclusions of function names. + # See the default value of `exclude` to get the builtin exclusions. + # Default: true + use-builtin-exclusions: true + # Ignore *_test.go files. + # Default: false + ignore-test: false + + bidichk: + # The following configurations check for all mentioned invisible unicode runes. + # All runes are enabled by default. + left-to-right-embedding: true + right-to-left-embedding: true + pop-directional-formatting: true + left-to-right-override: true + right-to-left-override: true + left-to-right-isolate: true + right-to-left-isolate: true + first-strong-isolate: true + pop-directional-isolate: true + + copyloopvar: + # Check all assigning the loop variable to another variable. + # Default: false + check-alias: false + cyclop: - # the maximal code complexity to report - max-complexity: 20 - # The maximal average package complexity. If it's higher than 0.0 (float), the check is enabled (default 0.0) + # The maximal code complexity to report. + # Default: 10 + max-complexity: 35 + # The maximal average package complexity. + # If it's higher than 0.0 (float) the check is enabled + # Default: 0.0 package-average: 0.0 - # should ignore tests (default false) + # Should ignore tests. + # Default: false skip-tests: false + decorder: + # Required order of `type`, `const`, `var` and `func` declarations inside a file. + # Default: types before constants before variables before functions. + dec-order: + - type + - const + - var + - func + + # If true, underscore vars (vars with "_" as the name) will be ignored at all checks + # Default: false (underscore vars are not ignored) + ignore-underscore-vars: false + + # If true, order of declarations is not checked at all. + # Default: true (disabled) + disable-dec-order-check: true + + # If true, `init` func can be anywhere in the file (does not have to be declared before all other functions). + # Default: true (disabled) + disable-init-func-first-check: false + + # If true, multiple global `type`, `const` and `var` declarations are allowed. + # Default: true (disabled) + disable-dec-num-check: true + + # If true, type declarations will be ignored for dec num check + # Default: false (type statements are not ignored) + disable-type-dec-num-check: false + + # If true, const declarations will be ignored for dec num check + # Default: false (const statements are not ignored) + disable-const-dec-num-check: false + + # If true, var declarations will be ignored for dec num check + # Default: false (var statements are not ignored) + disable-var-dec-num-check: false + + depguard: + # Rules to apply. + # + # Variables: + # - File Variables + # you can still use and exclamation mark ! in front of a variable to say not to use it. + # Example !$test will match any file that is not a go test file. + # + # `$all` - matches all go files + # `$test` - matches all go test files + # + # - Package Variables + # + # `$gostd` - matches all of go's standard library (Pulled from `GOROOT`) + # + # Default: Only allow $gostd in all files. + rules: + # Name of a rule. + main: + # Used to determine the package matching priority. + # There are three different modes: `original`, `strict`, and `lax`. + # Default: "original" + list-mode: original + # List of file globs that will match this list of settings to compare against. + # Default: $all + files: + - $all + # List of allowed packages. + allow: [] + # Packages that are not allowed where the value is a suggestion. + deny: + - pkg: "github.com/sirupsen/logrus" + desc: not allowed + - pkg: "github.com/pkg/errors" + desc: Should be replaced by standard lib errors package + + dogsled: + # Checks assignments with too many blank identifiers. + # Default: 2 + max-blank-identifiers: 2 + + dupl: + # Tokens count to trigger issue. + # Default: 150 + threshold: 100 + + dupword: + # Keywords for detecting duplicate words. + # If this list is not empty, only the words defined in this list will be detected. + # Default: [] + keywords: [] + # Keywords used to ignore detection. + # Default: [] + ignore: [] + errcheck: - # report about not checking of errors in type assertions: `a := b.(MyStruct)`; - # default is false: such cases aren't reported by default. + # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. + # Such cases aren't reported by default. + # Default: false check-type-assertions: false - # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; - # default is false: such cases aren't reported by default. + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`. + # Such cases aren't reported by default. + # Default: false check-blank: false - # list of functions to exclude from checking, where each entry is a single function to exclude. - # see https://github.com/kisielk/errcheck#excluding-functions for details + # To disable the errcheck built-in exclude list. + # See `-excludeonly` option in https://github.com/kisielk/errcheck#excluding-functions for details. + # Default: false + disable-default-exclusions: false + + # List of functions to exclude from checking, where each entry is a single function to exclude. + # See https://github.com/kisielk/errcheck#excluding-functions for details. exclude-functions: - - io/ioutil.ReadFile - io.Copy(*bytes.Buffer) - io.Copy(os.Stdout) + errchkjson: + # With check-error-free-encoding set to true, errchkjson does warn about errors + # from json encoding functions that are safe to be ignored, + # because they are not possible to happen. + # + # If check-error-free-encoding is set to true and errcheck linter is enabled, + # it is recommended to add the following exceptions to prevent from false positives: + # + # linters-settings: + # errcheck: + # exclude-functions: + # - encoding/json.Marshal + # - encoding/json.MarshalIndent + # + # Default: false + check-error-free-encoding: false + + # Issue on struct encoding that doesn't have exported fields. + # Default: false + report-no-exported: true + errorlint: - # Check whether fmt.Errorf uses the %w verb for formatting errors. See the readme for caveats + # Check whether fmt.Errorf uses the %w verb for formatting errors. + # See the https://github.com/polyfloyd/go-errorlint for caveats. + # Default: true errorf: true - # Check for plain type assertions and type switches + # Permit more than 1 %w verb, valid per Go 1.20 (Requires errorf:true) + # Default: true + errorf-multi: true + # Check for plain type assertions and type switches. + # Default: true asserts: true - # Check for plain error comparisons + # Check for plain error comparisons. + # Default: true comparison: true + # Allowed errors. + # Default: [] + allowed-errors: [] + # Allowed error "wildcards". + # Default: [] + allowed-errors-wildcard: [] + + exhaustive: + # Program elements to check for exhaustiveness. + # Default: [ switch ] + check: + - switch + - map + # Check switch statements in generated files also. + # Default: false + check-generated: false + # Presence of "default" case in switch statements satisfies exhaustiveness, + # even if all enum members are not listed. + # Default: false + default-signifies-exhaustive: false + # Enum members matching the supplied regex do not have to be listed in + # switch statements to satisfy exhaustiveness. + # Default: "" + ignore-enum-members: "" + # Enum types matching the supplied regex do not have to be listed in + # switch statements to satisfy exhaustiveness. + # Default: "" + ignore-enum-types: "" + # Consider enums only in package scopes, not in inner scopes. + # Default: false + package-scope-only: false + # Only run exhaustive check on switches with "//exhaustive:enforce" comment. + # Default: false + explicit-exhaustive-switch: false + # Only run exhaustive check on map literals with "//exhaustive:enforce" comment. + # Default: false + explicit-exhaustive-map: false + # Switch statement requires default case even if exhaustive. + # Default: false + default-case-required: false + + exhaustruct: + # List of regular expressions to match struct packages and their names. + # Regular expressions must match complete canonical struct package/name/structname. + # If this list is empty, all structs are tested. + # Default: [] + include: [] + # List of regular expressions to exclude struct packages and their names from checks. + # Regular expressions must match complete canonical struct package/name/structname. + # Default: [] + exclude: [] forbidigo: - # Forbid the following identifiers (identifiers are written using regexp): + # Forbid the following identifiers (list of regexp). + # Default: ["^(fmt\\.Print(|f|ln)|print|println)$"] forbid: + # Builtin function: - ^print.*$ - - 'fmt\.Print.*' - - ^spew\.Dump$ - # Exclude godoc examples from forbidigo checks. Default is true. + # Optional message that gets included in error reports. + - p: ^fmt\.Print.*$ + msg: Do not commit print statements. + # Alternatively, put messages at the end of the regex, surrounded by `(# )?` + # Escape any special characters. Those messages get included in error reports. + - 'fmt\.Print.*(# Do not commit print statements\.)?' + # Forbid spew Dump, whether it is called as function or method. + # Depends on analyze-types below. + - ^spew\.(ConfigState\.)?Dump$ + # The package name might be ambiguous. + # The full import path can be used as additional criteria. + # Depends on analyze-types below. + # - p: ^v1.Dump$ + # pkg: ^example.com/pkg/api/v1$ + # Exclude godoc examples from forbidigo checks. + # Default: true + exclude-godoc-examples: true + # Instead of matching the literal source code, + # use type information to replace expressions with strings that contain the package name + # and (for methods and fields) the type name. + # This makes it possible to handle import renaming and forbid struct fields and methods. + # Default: false + analyze-types: false + + funlen: + # Checks the number of lines in a function. + # If lower than 0, disable the check. + # Default: 60 + lines: 250 + # Checks the number of statements in a function. + # If lower than 0, disable the check. + # Default: 40 + statements: 100 + # Ignore comments when counting lines. + # Default false + ignore-comments: true + + gci: + # Section configuration to compare against. + # Section names are case-insensitive and may contain parameters in (). + # The default order of sections is `standard > default > custom > blank > dot > alias > localmodule`, + # If `custom-order` is `true`, it follows the order of `sections` option. + # Default: ["standard", "default"] + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/org/project) # Custom section: groups all imports with the specified Prefix. + - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + - alias # Alias section: contains all alias imports. This section is not present unless explicitly enabled. + - localmodule # Local module section: contains all local packages. This section is not present unless explicitly enabled. + + # Skip generated files. + # Default: true + skip-generated: true + + # Enable custom order of sections. + # If `true`, make the section order the same as the order of `sections`. + # Default: false + custom-order: true + + ginkgolinter: + # Suppress the wrong length assertion warning. + # Default: false + suppress-len-assertion: true + + # Suppress the wrong nil assertion warning. + # Default: false + suppress-nil-assertion: true + + # Suppress the wrong error assertion warning. + # Default: false + suppress-err-assertion: true + + # Suppress the wrong comparison assertion warning. + # Default: false + suppress-compare-assertion: true + + # Suppress the function all in async assertion warning. + # Default: false + suppress-async-assertion: true + + # Suppress warning for comparing values from different types, like `int32` and `uint32` + # Default: false + suppress-type-compare-assertion: true + + # Trigger warning for ginkgo focus containers like `FDescribe`, `FContext`, `FWhen` or `FIt` + # Default: false + forbid-focus-container: true + + # Don't trigger warnings for HaveLen(0) + # Default: false + allow-havelen-zero: true + + # Force using `Expect` with `To`, `ToNot` or `NotTo`. + # Reject using `Expect` with `Should` or `ShouldNot`. + # Default: false + force-expect-to: true + + # Best effort validation of async intervals (timeout and polling). + # Ignored the suppress-async-assertion is true. + # Default: false + validate-async-intervals: true + + # Trigger a warning for variable assignments in ginkgo containers like `Describe`, `Context` and `When`, instead of in `BeforeEach()`. + # Default: false + forbid-spec-pollution: true gocognit: - # minimal code complexity to report, 30 by default (but we recommend 10-20) - min-complexity: 20 + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 35 + + goconst: + # Minimal length of string constant. + # Default: 3 + min-len: 3 + # Minimum occurrences of constant string count to trigger issue. + # Default: 3 + min-occurrences: 3 + # Ignore test files. + # Default: false + ignore-tests: true + # Look for existing constants matching the values. + # Default: true + match-constant: true + # Search also for duplicated numbers. + # Default: false + numbers: false + # Minimum value, only works with goconst.numbers + # Default: 3 + min: 3 + # Maximum value, only works with goconst.numbers + # Default: 3 + max: 3 + # Ignore when constant is not used as function argument. + # Default: true + ignore-calls: true + # Exclude strings matching the given regular expression. + # Default: "" + ignore-strings: '' + + gocritic: + # Disable all checks. + # Default: false + disable-all: false + # Which checks should be enabled in addition to default checks; can't be combined with 'disabled-checks'. + # By default, list of stable checks is used (https://go-critic.github.io/overview#checks-overview): + # appendAssign, argOrder, assignOp, badCall, badCond, captLocal, caseOrder, codegenComment, commentFormatting, + # defaultCaseOrder, deprecatedComment, dupArg, dupBranchBody, dupCase, dupSubExpr, elseif, exitAfterDefer, + # flagDeref, flagName, ifElseChain, mapKey, newDeref, offBy1, regexpMust, singleCaseSwitch, sloppyLen, + # sloppyTypeAssert, switchTrue, typeSwitchVar, underef, unlambda, unslice, valSwap, wrapperFunc + # To see which checks are enabled run `GL_DEBUG=gocritic golangci-lint run --enable=gocritic`. + enabled-checks: [] + + # Enable all checks. + # Default: false + enable-all: true + # Which checks should be disabled; can't be combined with 'enabled-checks'. + # Default: [] + disabled-checks: ["sloppyReassign", "preferFprint", "importShadow"] + + # Enable multiple checks by tags in addition to default checks. + # Run `GL_DEBUG=gocritic golangci-lint run --enable=gocritic` to see all tags and checks. + # See https://github.com/go-critic/go-critic#usage -> section "Tags". + # Default: [] + enabled-tags: [] + disabled-tags: [] + + # Settings passed to gocritic. + # The settings key is the name of a supported gocritic checker. + # The list of supported checkers can be found in https://go-critic.github.io/overview. + settings: + # Must be valid enabled check name. + captLocal: + # Whether to restrict checker to params only. + # Default: true + paramsOnly: true + commentedOutCode: + # Min length of the comment that triggers a warning. + # Default: 15 + minLength: 15 + elseif: + # Whether to skip balanced if-else pairs. + # Default: true + skipBalanced: true + hugeParam: + # Size in bytes that makes the warning trigger. + # Default: 80 + sizeThreshold: 80 + ifElseChain: + # Min number of if-else blocks that makes the warning trigger. + # Default: 2 + minThreshold: 2 + nestingReduce: + # Min number of statements inside a branch to trigger a warning. + # Default: 5 + bodyWidth: 5 + rangeExprCopy: + # Size in bytes that makes the warning trigger. + # Default: 512 + sizeThreshold: 512 + # Whether to check test functions + # Default: true + skipTestFuncs: true + rangeValCopy: + # Size in bytes that makes the warning trigger. + # Default: 128 + sizeThreshold: 128 + # Whether to check test functions. + # Default: true + skipTestFuncs: true + ruleguard: + # Enable debug to identify which 'Where' condition was rejected. + # The value of the parameter is the name of a function in a ruleguard file. + # + # When a rule is evaluated: + # If: + # The Match() clause is accepted; and + # One of the conditions in the Where() clause is rejected, + # Then: + # ruleguard prints the specific Where() condition that was rejected. + # + # The option is passed to the ruleguard 'debug-group' argument. + # Default: "" + debug: '' + # Determines the behavior when an error occurs while parsing ruleguard files. + # If flag is not set, log error and skip rule files that contain an error. + # If flag is set, the value must be a comma-separated list of error conditions. + # - 'all': fail on all errors. + # - 'import': ruleguard rule imports a package that cannot be found. + # - 'dsl': gorule file does not comply with the ruleguard DSL. + # Default: "" + failOn: "" + # Comma-separated list of file paths containing ruleguard rules. + # If a path is relative, it is relative to the directory where the golangci-lint command is executed. + # The special '${configDir}' variable is substituted with the absolute directory containing the golangci config file. + # Glob patterns such as 'rules-*.go' may be specified. + # Default: "" + rules: '' + # Comma-separated list of enabled groups or skip empty to enable everything. + # Tags can be defined with # character prefix. + # Default: "" + enable: "" + # Comma-separated list of disabled groups or skip empty to enable everything. + # Tags can be defined with # character prefix. + # Default: "" + disable: "" + tooManyResultsChecker: + # Maximum number of results. + # Default: 5 + maxResults: 10 + truncateCmp: + # Whether to skip int/uint/uintptr types. + # Default: true + skipArchDependent: true + underef: + # Whether to skip (*x).method() calls where x is a pointer receiver. + # Default: true + skipRecvDeref: true + unnamedResult: + # Whether to check exported functions. + # Default: false + checkExported: true + + gocyclo: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 35 + + godot: + # Comments to be checked: `declarations`, `toplevel`, or `all`. + # Default: declarations + scope: declarations + # List of regexps for excluding particular comment lines from check. + # Default: [] + exclude: + # Exclude todo and fixme comments. + - "^fixme:" + - "^todo:" + # Check that each sentence ends with a period. + # Default: true + period: false + # Check that each sentence starts with a capital letter. + # Default: false + capital: false + + godox: + # Report any comments starting with keywords, this is useful for TODO or FIXME comments that + # might be left in the code accidentally and should be resolved before merging. + # Default: ["TODO", "BUG", "FIXME"] + keywords: [] gofmt: - # simplify code: gofmt with `-s` option, true by default + # Simplify code: gofmt with `-s` option. + # Default: true simplify: true + # Apply the rewrite rules to the source before reformatting. + # https://pkg.go.dev/cmd/gofmt + # Default: [] + rewrite-rules: + - pattern: 'interface{}' + replacement: 'any' + - pattern: 'a[b:len(a)]' + replacement: 'a[b:]' + + gofumpt: + # Module path which contains the source code being formatted. + # Default: "" + module-path: "" + + # Choose whether to use the extra rules. + # Default: false + extra-rules: true + + goheader: + # Supports two types 'const` and `regexp`. + # Values can be used recursively. + # Default: {} + values: {} + # The template use it for checking. + # Default: "" + template: "" + # As an alternative of directive 'template', you may put the path to file with the template source. + # Useful if you need to load the template from a specific file. + # Default: "" + # template-path: "" + + goimports: + # A comma-separated list of prefixes, which, if set, checks import paths + # with the given prefixes are grouped after 3rd-party packages. + # Default: "" + local-prefixes: "" + + gomoddirectives: + # Allow local `replace` directives. + # Default: false + replace-local: false + # List of allowed `replace` directives. + # Default: [] + replace-allow-list: [] + # Allow not explaining why the version has been retracted in the `retract` directives. + # Default: false + retract-allow-no-explanation: false + # Forbid the use of the `exclude` directives. + # Default: false + exclude-forbidden: false + + gomodguard: + allowed: + # List of allowed modules. + # Default: [] + modules: [] + # List of allowed module domains. + # Default: [] + domains: [] + blocked: + # List of blocked modules. + # Default: [] + modules: [] + # List of blocked module version constraints. + # Default: [] + versions: [] + # Set to true to raise lint issues for packages that are loaded from a local path via replace directive. + # Default: false + local_replace_directives: false + + gosimple: + # Sxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Default: ["*"] + checks: [ "*" ] gosec: + # To select a subset of rules to run. + # Available rules: https://github.com/securego/gosec#available-rules + # Default: [] - means include all rules + includes: [] + # To specify a set of rules to explicitly exclude. # Available rules: https://github.com/securego/gosec#available-rules + # Default: [] excludes: - # Look for bad TLS connection settings - # Disable it, since we don't use encrypted connection for inter-service communication. - - G402 - # Poor file permissions used when writing to a new file - # We only write files in codegen utils. So, there is no sense to set permissions 600 fot a new file. - - G306 - # Insecure random number source (rand) - # We don't actually need a crypto-safe random numbers. - - G404 + - G501 # Blocklisted import crypto/md5: weak cryptographic primitive + - G401 # Use of weak cryptographic primitive + + # Exclude generated files + # Default: false + exclude-generated: false + + # Filter out the issues with a lower severity than the given value. + # Valid options are: low, medium, high. + # Default: low + severity: low + + # Filter out the issues with a lower confidence than the given value. + # Valid options are: low, medium, high. + # Default: low + confidence: low + + # Concurrency value. + # Default: the number of logical CPUs usable by the current process. + concurrency: 4 + + # To specify the configuration of rules. + config: + # Globals are applicable to all rules. + global: + # If true, ignore #nosec in comments (and an alternative as well). + # Default: false + nosec: false + # Add an alternative comment prefix to #nosec (both will work at the same time). + # Default: "" + "#nosec": "" + # Define whether nosec issues are counted as finding or not. + # Default: false + show-ignored: false + # Audit mode enables addition checks that for normal code analysis might be too nosy. + # Default: false + audit: false + G101: + # Regexp pattern for variables and constants to find. + # Default: "(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred" + pattern: "(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred" + # If true, complain about all cases (even with low entropy). + # Default: false + ignore_entropy: false + # Maximum allowed entropy of the string. + # Default: "80.0" + entropy_threshold: "80.0" + # Maximum allowed value of entropy/string length. + # Is taken into account if entropy >= entropy_threshold/2. + # Default: "3.0" + per_char_threshold: "3.0" + # Calculate entropy for first N chars of the string. + # Default: "16" + truncate: "16" + # Additional functions to ignore while checking unhandled errors. + # Following functions always ignored: + # bytes.Buffer: + # - Write + # - WriteByte + # - WriteRune + # - WriteString + # fmt: + # - Print + # - Printf + # - Println + # - Fprint + # - Fprintf + # - Fprintln + # strings.Builder: + # - Write + # - WriteByte + # - WriteRune + # - WriteString + # io.PipeWriter: + # - CloseWithError + # hash.Hash: + # - Write + # os: + # - Unsetenv + # Default: {} + G104: + fmt: + - Fscanf + G111: + # Regexp pattern to find potential directory traversal. + # Default: "http\\.Dir\\(\"\\/\"\\)|http\\.Dir\\('\\/'\\)" + pattern: "http\\.Dir\\(\"\\/\"\\)|http\\.Dir\\('\\/'\\)" + # Maximum allowed permissions mode for os.Mkdir and os.MkdirAll + # Default: "0750" + G301: "0750" + # Maximum allowed permissions mode for os.OpenFile and os.Chmod + # Default: "0600" + G302: "0600" + # Maximum allowed permissions mode for os.WriteFile and ioutil.WriteFile + # Default: "0600" + G306: "0600" + + gosmopolitan: + # Allow and ignore `time.Local` usages. + # + # Default: false + allow-time-local: false + # List of fully qualified names in the `full/pkg/path.name` form, to act as "i18n escape hatches". + # String literals inside call-like expressions to, or struct literals of those names, + # are exempt from the writing system check. + # + # Default: [] + escape-hatches: [] + # Ignore test files. + # + # Default: true + ignore-tests: true + # List of Unicode scripts to watch for any usage in string literals. + # https://pkg.go.dev/unicode#pkg-variables + # + # Default: ["Han"] + watch-for-scripts: [] govet: - # settings per analyzer + # Disable all analyzers. + # Default: false + disable-all: false + # Enable analyzers by name. + # (in addition to default: + # appends, asmdecl, assign, atomic, bools, buildtag, cgocall, composites, copylocks, defers, directive, errorsas, + # framepointer, httpresponse, ifaceassert, loopclosure, lostcancel, nilfunc, printf, shift, sigchanyzer, slog, + # stdmethods, stringintconv, structtag, testinggoroutine, tests, timeformat, unmarshal, unreachable, unsafeptr, + # unusedresult + # ). + # Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers. + # Default: [] + enable: [] + # Enable all analyzers. + # Default: false + enable-all: true + # Disable analyzers by name. + # (in addition to default + # atomicalign, deepequalerrors, fieldalignment, findcall, nilness, reflectvaluecompare, shadow, sortslice, + # timeformat, unusedwrite + # ). + # Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers. + # Default: [] + disable: + - fieldalignment + # Settings per analyzer. settings: - shadow: - # Whether to be strict about shadowing; can be noisy. - # Default: false - strict: true - printf: # analyzer name, run `go tool vet help` to see all analyzers - funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer + # Analyzer name, run `go tool vet help` to see all analyzers. + printf: + # Comma-separated list of print function names to check (in addition to default, see `go tool vet help printf`). + # Default: [] + funcs: - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + shadow: + # Whether to be strict about shadowing; can be noisy. + # Default: false + strict: true + unusedresult: + # Comma-separated list of functions whose results must be used + # (in addition to default: + # context.WithCancel, context.WithDeadline, context.WithTimeout, context.WithValue, errors.New, fmt.Errorf, + # fmt.Sprint, fmt.Sprintf, sort.Reverse + # ). + # Default: [] + funcs: [] + # Comma-separated list of names of methods of type func() string whose results must be used + # (in addition to default Error,String) + # Default: [] + stringmethods: [] - # enable or disable analyzers by name - # run `go tool vet help` to see all analyzers - enable: [ ] - enable-all: true - disable: - - fieldalignment - disable-all: false + grouper: + # Require the use of a single global 'const' declaration only. + # Default: false + const-require-single-const: false + # Require the use of grouped global 'const' declarations. + # Default: false + const-require-grouping: false + + # Require the use of a single 'import' declaration only. + # Default: false + import-require-single-import: false + # Require the use of grouped 'import' declarations. + # Default: false + import-require-grouping: false + + # Require the use of a single global 'type' declaration only. + # Default: false + type-require-single-type: false + # Require the use of grouped global 'type' declarations. + # Default: false + type-require-grouping: false + + # Require the use of a single global 'var' declaration only. + # Default: false + var-require-single-var: false + # Require the use of grouped global 'var' declarations. + # Default: false + var-require-grouping: false + + importas: + # Do not allow unaliased imports of aliased packages. + # Default: false + no-unaliased: true + # Do not allow non-required aliases. + # Default: false + no-extra-aliases: true + # List of aliases + # Default: [] + alias: [] + + inamedparam: + # Skips check for interface methods with only a single parameter. + # Default: false + skip-single-param: false + + interfacebloat: + # The maximum number of methods allowed for an interface. + # Default: 10 + max: 10 + + ireturn: + # ireturn does not allow using `allow` and `reject` settings at the same time. + # Both settings are lists of the keywords and regular expressions matched to interface or package names. + # Keywords: + # - `empty` for `interface{}` + # - `error` for errors + # - `stdlib` for standard library + # - `anon` for anonymous interfaces + # - `generic` for generic interfaces added in go 1.18 + + # By default, it allows using errors, empty interfaces, anonymous interfaces, + # and interfaces provided by the standard library. + allow: [] + # reject-list of interfaces + reject: [] + + lll: + # Max line length, lines longer will be reported. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option. + # Default: 120. + line-length: 120 + # Tab width in spaces. + # Default: 1 + tab-width: 1 + + loggercheck: + # Allow check for the github.com/go-kit/log library. + # Default: true + kitlog: false + # Allow check for the k8s.io/klog/v2 library. + # Default: true + klog: false + # Allow check for the github.com/go-logr/logr library. + # Default: true + logr: false + # Allow check for the "sugar logger" from go.uber.org/zap library. + # Default: true + zap: false + # Require all logging keys to be inlined constant strings. + # Default: false + require-string-key: false + # Require printf-like format specifier (%s, %d for example) not present. + # Default: false + no-printf-like: false + # List of custom rules to check against, where each rule is a single logger pattern, useful for wrapped loggers. + # For example: https://github.com/timonwong/loggercheck/blob/7395ab86595781e33f7afba27ad7b55e6956ebcd/testdata/custom-rules.txt + # Default: empty + rules: [] + + maintidx: + # Show functions with maintainability index lower than N. + # A high index indicates better maintainability (it's kind of the opposite of complexity). + # Default: 20 + under: 20 makezero: - # Allow only slices initialized with a length of zero. Default is false. + # Allow only slices initialized with a length of zero. + # Default: false always: false + misspell: + # Correct spellings using locale preferences for US or UK. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + # Default is to use a neutral variety of English. + locale: US + # Typos to ignore. + # Should be in lower case. + # Default: [] + ignore-words: ["payed"] + # Extra word corrections. + # `typo` and `correction` should only contain letters. + # The words are case-insensitive. + # Default: [] + extra-words: [] + # Mode of the analysis: + # - default: checks all the file content. + # - restricted: checks only comments. + # Default: "" + mode: "default" + + mnd: + # List of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description. + # Default: ["argument", "case", "condition", "operation", "return", "assign"] + checks: + - argument + - case + - condition + - operation + - return + - assign + # List of numbers to exclude from analysis. + # The numbers should be written as string. + # Values always ignored: "1", "1.0", "0" and "0.0" + # Default: [] + ignored-numbers: + - '0666' + - '0755' + # List of file patterns to exclude from analysis. + # Values always ignored: `.+_test.go` + # Default: [] + ignored-files: [] + # List of function patterns to exclude from analysis. + # Following functions are always ignored: `time.Date`, + # `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`, + # `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`. + # Default: [] + ignored-functions: [] + + musttag: + # A set of custom functions to check in addition to the builtin ones. + # Default: json, xml, gopkg.in/yaml.v3, BurntSushi/toml, mitchellh/mapstructure, jmoiron/sqlx + functions: [] + + nakedret: + # Make an issue if func has more lines of code than this setting, and it has naked returns. + # Default: 30 + max-func-lines: 30 + + nestif: + # Minimal complexity of if statements to report. + # Default: 5 + min-complexity: 6 + + nilnil: + # List of return types to check. + # Default: ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"] + checked-types: + - ptr + - func + - iface + - map + - chan + - uintptr + - unsafeptr + + nlreturn: + # Size of the block (including a return statement that is still "OK") + # so no return split required. + # Default: 1 + block-size: 1 + + nolintlint: + # Disable to ensure that all nolint directives actually have an effect. + # Default: false + allow-unused: false + # Exclude following linters from requiring an explanation. + # Default: [] + allow-no-explanation: [ ] + # Enable to require an explanation of nonzero length after each nolint directive. + # Default: false + require-explanation: false + # Enable to require nolint directives to mention the specific linter being suppressed. + # Default: false + require-specific: false + + nonamedreturns: + # Report named error if it is assigned inside defer. + # Default: false + report-error-in-defer: false + + paralleltest: + # Ignore missing calls to `t.Parallel()` and only report incorrect uses of it. + # Default: false + ignore-missing: false + # Ignore missing calls to `t.Parallel()` in subtests. Top-level tests are + # still required to have `t.Parallel`, but subtests are allowed to skip it. + # Default: false + ignore-missing-subtests: false + + perfsprint: + # Optimizes even if it requires an int or uint type cast. + # Default: true + int-conversion: true + # Optimizes into `err.Error()` even if it is only equivalent for non-nil errors. + # Default: false + err-error: true + # Optimizes `fmt.Errorf`. + # Default: true + errorf: true + # Optimizes `fmt.Sprintf` with only one argument. + # Default: true + sprintf1: true + # Optimizes into strings concatenation. + # Default: true + strconcat: true + + prealloc: + # IMPORTANT: we don't recommend using this linter before doing performance profiling. + # For most programs usage of prealloc will be a premature optimization. + + # Report pre-allocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. + # Default: true + simple: true + # Report pre-allocation suggestions on range loops. + # Default: true + range-loops: true + # Report pre-allocation suggestions on for loops. + # Default: false + for-loops: true + predeclared: - # comma-separated list of predeclared identifiers to not report on + # Comma-separated list of predeclared identifiers to not report on. + # Default: "" ignore: "" - # include method names and field names (i.e., qualified names) in checks + # Include method names and field names (i.e., qualified names) in checks. + # Default: false q: false + promlinter: + # Promlinter cannot infer all metrics name in static analysis. + # Enable strict mode will also include the errors caused by failing to parse the args. + # Default: false + strict: true + # Please refer to https://github.com/yeya24/promlinter#usage for detailed usage. + # Default: [] + disabled-linters: [] + + protogetter: + # Skip files generated by specified generators from the checking. + # Checks only the file's initial comment, which must follow the format: "// Code generated by ". + # Files generated by protoc-gen-go, protoc-gen-go-grpc, and protoc-gen-grpc-gateway are always excluded automatically. + # Default: [] + skip-generated-by: [""] + # Skip files matching the specified glob pattern from the checking. + # Default: [] + skip-files: [] + # Skip any generated files from the checking. + # Default: false + skip-any-generated: false + # Skip first argument of append function. + # Default: false + replace-first-arg-in-append: false + + reassign: + # Patterns for global variable names that are checked for reassignment. + # See https://github.com/curioswitch/go-reassign#usage + # Default: ["EOF", "Err.*"] + patterns: [] + + revive: + # Maximum number of open files at the same time. + # See https://github.com/mgechev/revive#command-line-flags + # Defaults to unlimited. + max-open-files: 2048 + + # When set to false, ignores files with "GENERATED" header, similar to golint. + # See https://github.com/mgechev/revive#available-rules for details. + # Default: false + ignore-generated-header: false + + # Sets the default severity. + # See https://github.com/mgechev/revive#configuration + # Default: warning + severity: error + + # Enable all available rules. + # Default: false + enable-all-rules: true + + # Sets the default failure confidence. + # This means that linting errors with less than 0.8 confidence will be ignored. + # Default: 0.8 + confidence: 0.8 + + rules: [] + + rowserrcheck: + # database/sql is always checked + # Default: [] + packages: [] + + sloglint: + # Enforce not mixing key-value pairs and attributes. + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-mixed-arguments + # Default: true + no-mixed-args: true + # Enforce using key-value pairs only (overrides no-mixed-args, incompatible with attr-only). + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#key-value-pairs-only + # Default: false + kv-only: true + # Enforce using attributes only (overrides no-mixed-args, incompatible with kv-only). + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#attributes-only + # Default: false + attr-only: false + # Enforce not using global loggers. + # Values: + # - "": disabled + # - "all": report all global loggers + # - "default": report only the default slog logger + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-global + # Default: "" + no-global: "all" + # Enforce using methods that accept a context. + # Values: + # - "": disabled + # - "all": report all contextless calls + # - "scope": report only if a context exists in the scope of the outermost function + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#context-only + # Default: "" + context: "all" + # Enforce using static values for log messages. + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#static-messages + # Default: false + static-msg: true + # Enforce using constants instead of raw keys. + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-raw-keys + # Default: false + no-raw-keys: true + # Enforce a single key naming convention. + # Values: snake, kebab, camel, pascal + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#key-naming-convention + # Default: "" + key-naming-case: snake + # Enforce not using specific keys. + # Default: [] + forbidden-keys: + - time + - level + - msg + - source + # Enforce putting arguments on separate lines. + # https://github.com/go-simpler/sloglint?tab=readme-ov-file#forbidden-keys + # Default: false + args-on-sep-lines: true + + spancheck: + # Checks to enable. + # Options include: + # - `end`: check that `span.End()` is called + # - `record-error`: check that `span.RecordError(err)` is called when an error is returned + # - `set-status`: check that `span.SetStatus(codes.Error, msg)` is called when an error is returned + # Default: ["end"] + checks: ["end"] + # A list of regexes for function signatures that silence `record-error` and `set-status` reports + # if found in the call path to a returned error. + # https://github.com/jjti/go-spancheck#ignore-check-signatures + # Default: [] + ignore-check-signatures: [] + # A list of regexes for additional function signatures that create spans. + # This is useful if you have a utility method to create spans. + # Each entry should be of the form `:`, where `telemetry-type` can be `opentelemetry` or `opencensus`. + # https://github.com/jjti/go-spancheck#extra-start-span-signatures + # Default: [] + extra-start-span-signatures: [] staticcheck: - # Select the Go version to target. The default is '1.13'. - # https://staticcheck.io/docs/options#checks - checks: [ "all" ] + # SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Default: ["*"] + checks: ["*"] + + stylecheck: + # STxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Default: ["*"] + checks: ["-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"] + # https://staticcheck.io/docs/configuration/options/#dot_import_whitelist + # Default: ["github.com/mmcloughlin/avo/build", "github.com/mmcloughlin/avo/operand", "github.com/mmcloughlin/avo/reg"] + dot-import-whitelist: [] + # https://staticcheck.io/docs/configuration/options/#initialisms + # Default: ["ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS"] + initialisms: [ "ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS" ] + # https://staticcheck.io/docs/configuration/options/#http_status_code_whitelist + # Default: ["200", "400", "404", "500"] + http-status-code-whitelist: [ "200", "400", "404", "500" ] + + tagalign: + # Align and sort can be used together or separately. + # + # Whether enable align. If true, the struct tags will be aligned. + # e.g.: + # type FooBar struct { + # Bar string `json:"bar" validate:"required"` + # FooFoo int8 `json:"foo_foo" validate:"required"` + # } + # will be formatted to: + # type FooBar struct { + # Bar string `json:"bar" validate:"required"` + # FooFoo int8 `json:"foo_foo" validate:"required"` + # } + # Default: true. + align: false + # Whether enable tags sort. + # If true, the tags will be sorted by name in ascending order. + # e.g.: `xml:"bar" json:"bar" validate:"required"` -> `json:"bar" validate:"required" xml:"bar"` + # Default: true + sort: false + # Specify the order of tags, the other tags will be sorted by name. + # This option will be ignored if `sort` is false. + # Default: [] + order: + - json + - yaml + - yml + - toml + - mapstructure + - binding + - validate + # Whether enable strict style. + # In this style, the tags will be sorted and aligned in the dictionary order, + # and the tags with the same name will be aligned together. + # Note: This option will be ignored if 'align' or 'sort' is false. + # Default: false + strict: true + + tagliatelle: + # Check the struct tag name case. + case: + # Use the struct field name to check the name of the struct tag. + # Default: false + use-field-name: true + # `camel` is used for `json` and `yaml`, and `header` is used for `header` (can be overridden) + # Default: {} + rules: + # Any struct tag type can be used. + # Support string case: `camel`, `pascal`, `kebab`, `snake`, `upperSnake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`, `header` + json: camel + yaml: camel + xml: camel + toml: camel + bson: camel + avro: snake + mapstructure: kebab + env: upperSnake + envconfig: upperSnake + + tenv: + # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. + # Otherwise, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked. + # Default: false + all: false + + testifylint: + # Enable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + enable-all: true + # Disable checkers by name + # (in addition to default + # suite-thelper + # ). + disable: [] + # Disable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + disable-all: false + # Enable checkers by name + # (in addition to default + # blank-import, bool-compare, compares, empty, error-is-as, error-nil, expected-actual, go-require, float-compare, + # len, negative-positive, nil-compare, require-error, suite-dont-use-pkg, suite-extra-assert-call, useless-assert + # ). + enable: [] + bool-compare: + # To ignore user defined types (over builtin bool). + # Default: false + ignore-custom-types: true + expected-actual: + # Regexp for expected variable name. + # Default: (^(exp(ected)?|want(ed)?)([A-Z]\w*)?$)|(^(\w*[a-z])?(Exp(ected)?|Want(ed)?)$) + pattern: ^expected + go-require: + # To ignore HTTP handlers (like http.HandlerFunc). + # Default: false + ignore-http-handlers: true + require-error: + # Regexp for assertions to analyze. If defined, then only matched error assertions will be reported. + # Default: "" + fn-pattern: ^(Errorf?|NoErrorf?)$ + suite-extra-assert-call: + # To require or remove extra Assert() call? + # Default: remove + mode: require + + testpackage: + # Regexp pattern to skip files. + # Default: "(export|internal)_test\\.go" + skip-regexp: (export|internal)_test\.go + # List of packages that don't end with _test that tests are allowed to be in. + # Default: "main" + allow-packages: + - example + - main + + thelper: + test: + # Check *testing.T is first param (or after context.Context) of helper function. + # Default: true + first: true + # Check *testing.T param has name t. + # Default: true + name: true + # Check t.Helper() begins helper function. + # Default: true + begin: true + benchmark: + # Check *testing.B is first param (or after context.Context) of helper function. + # Default: true + first: true + # Check *testing.B param has name b. + # Default: true + name: true + # Check b.Helper() begins helper function. + # Default: true + begin: true + tb: + # Check *testing.TB is first param (or after context.Context) of helper function. + # Default: true + first: true + # Check *testing.TB param has name tb. + # Default: true + name: true + # Check tb.Helper() begins helper function. + # Default: true + begin: true + fuzz: + # Check *testing.F is first param (or after context.Context) of helper function. + # Default: true + first: true + # Check *testing.F param has name f. + # Default: true + name: true + # Check f.Helper() begins helper function. + # Default: true + begin: true + + usestdlibvars: + # Suggest the use of http.MethodXX. + # Default: true + http-method: true + # Suggest the use of http.StatusXX. + # Default: true + http-status-code: true + # Suggest the use of time.Weekday.String(). + # Default: true + time-weekday: true + # Suggest the use of time.Month.String(). + # Default: false + time-month: true + # Suggest the use of time.Layout. + # Default: false + time-layout: true + # Suggest the use of crypto.Hash.String(). + # Default: false + crypto-hash: false + # Suggest the use of rpc.DefaultXXPath. + # Default: false + default-rpc-path: false + # Suggest the use of sql.LevelXX.String(). + # Default: false + sql-isolation-level: false + # Suggest the use of tls.SignatureScheme.String(). + # Default: false + tls-signature-scheme: false + # Suggest the use of constant.Kind.String(). + # Default: false + constant-kind: false + + unconvert: + # Remove conversions that force intermediate rounding. + # Default: false + fast-math: false + # Be more conservative (experimental). + # Default: false + safe: false unparam: - # Inspect exported functions, default is false. Set to true if no external program/library imports your code. + # Inspect exported functions. + # + # Set to true if no external program/library imports your code. # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: # if it's called for subdir of a project it can't find external interfaces. All text editor integrations # with golangci-lint call it on a directory with the changed file. + # + # Default: false check-exported: false unused: @@ -168,7 +1561,7 @@ linters-settings: field-writes-are-uses: true # Treat IncDec statement (e.g. `i++` or `i--`) as both read and write operation instead of just write. # Default: false - post-statements-are-reads: true + post-statements-are-reads: false # Mark all exported identifiers as used. # Default: true exported-is-used: true @@ -185,206 +1578,344 @@ linters-settings: # Default: true generated-is-used: true - dupl: - # tokens count to trigger issue, 150 by default - threshold: 100 + varnamelen: + # The longest distance, in source lines, that is being considered a "small scope". + # Variables used in at most this many lines will be ignored. + # Default: 5 + max-distance: 5 + # The minimum length of a variable's name that is considered "long". + # Variable names that are at least this long will be ignored. + # Default: 3 + min-name-length: 3 + # Check method receivers. + # Default: false + check-receiver: false + # Check named return values. + # Default: false + check-return: false + # Check type parameters. + # Default: false + check-type-param: false + # Ignore "ok" variables that hold the bool return value of a type assertion. + # Default: false + ignore-type-assert-ok: false + # Ignore "ok" variables that hold the bool return value of a map index. + # Default: false + ignore-map-index-ok: false + # Ignore "ok" variables that hold the bool return value of a channel receive. + # Default: false + ignore-chan-recv-ok: false + # Optional list of variable names that should be ignored completely. + # Default: [] + ignore-names: [] + # Optional list of variable declarations that should be ignored completely. + # Entries must be in one of the following forms (see below for examples): + # - for variables, parameters, named return values, method receivers, or type parameters: + # ( can also be a pointer/slice/map/chan/...) + # - for constants: const + # + # Default: [] + ignore-decls: [] - exhaustive: - # check switch statements in generated files also - check-generated: false - # presence of "default" case in switch statements satisfies exhaustiveness, - # even if all enum members are not listed - default-signifies-exhaustive: true - # enum members matching the supplied regex do not have to be listed in - # switch statements to satisfy exhaustiveness - ignore-enum-members: "" - # consider enums only in package scopes, not in inner scopes - package-scope-only: false + whitespace: + # Enforces newlines (or comments) after every multi-line if statement. + # Default: false + multi-if: false + # Enforces newlines (or comments) after every multi-line function signature. + # Default: false + multi-func: false - funlen: - lines: 60 - statements: 40 + wrapcheck: + # An array of strings that specify substrings of signatures to ignore. + # If this set, it will override the default set of ignored signatures. + # See https://github.com/tomarrell/wrapcheck#configuration for more information. + # Default: [".Errorf(", "errors.New(", "errors.Unwrap(", "errors.Join(", ".Wrap(", ".Wrapf(", ".WithMessage(", ".WithMessagef(", ".WithStack("] + ignoreSigs: + - .Errorf( + - errors.New( + - errors.Unwrap( + - errors.Join( + - .Wrap( + - .Wrapf( + - .WithMessage( + - .WithMessagef( + - .WithStack( + # An array of strings that specify regular expressions of signatures to ignore. + # Default: [] + ignoreSigRegexps: [] + # An array of strings that specify globs of packages to ignore. + # Default: [] + ignorePackageGlobs: [] + # An array of strings that specify regular expressions of interfaces to ignore. + # Default: [] + ignoreInterfaceRegexps: [] - goconst: - # minimal length of string constant, 3 by default - min-len: 3 - # minimum occurrences of constant string count to trigger issue, 3 by default - min-occurrences: 3 - # ignore test files, false by default - ignore-tests: true - # look for existing constants matching the values, true by default - match-constant: true - # search also for duplicated numbers, false by default - numbers: false - # minimum value, only works with goconst.numbers, 3 by default - min: 3 - # maximum value, only works with goconst.numbers, 3 by default - max: 3 - # ignore when constant is not used as function argument, true by default - ignore-calls: true + wsl: + # See https://github.com/bombsimon/wsl/blob/master/doc/configuration.md for documentation of available settings. + # These are the defaults for `golangci-lint`. - goimports: - # put imports beginning with prefix after 3rd-party packages; - # it's a comma-separated list of prefixes - local-prefixes: github.com/headframe-io + # Do strict checking when assigning from append (x = append(x, y)). If + # this is set to true - the append call must append either a variable + # assigned, called or used on the line above. + strict-append: true - gosimple: - # Select the Go version to target. The default is '1.13'. - # https://staticcheck.io/docs/options#checks - checks: [ "all" ] + # Allows assignments to be cuddled with variables used in calls on + # line above and calls to be cuddled with assignments of variables + # used in call on line above. + allow-assign-and-call: true - nakedret: - # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 - max-func-lines: 5 + # Allows assignments to be cuddled with anything. + allow-assign-and-anything: false - nestif: - # minimal complexity of if statements to report, 5 by default - min-complexity: 6 + # Allows cuddling to assignments even if they span over multiple lines. + allow-multiline-assign: true - prealloc: - # XXX: we don't recommend using this linter before doing performance profiling. - # For most programs usage of prealloc will be a premature optimization. + # If the number of lines in a case block is equal to or lager than this + # number, the case *must* end white a newline. + force-case-trailing-whitespace: 0 - # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. - # True by default. - simple: true - range-loops: true # Report preallocation suggestions on range loops, true by default - for-loops: false # Report preallocation suggestions on for loops, false by default + # Allow blocks to end with comments. + allow-trailing-comment: false + + # Allow multiple comments in the beginning of a block separated with newline. + allow-separated-leading-comment: false + + # Allow multiple var/declaration statements to be cuddled. + allow-cuddle-declarations: false + + # A list of call idents that everything can be cuddled with. + # Defaults to calls looking like locks. + allow-cuddle-with-calls: [ "Lock", "RLock" ] + + # AllowCuddleWithRHS is a list of right hand side variables that is allowed + # to be cuddled with anything. Defaults to assignments or calls looking + # like unlocks. + allow-cuddle-with-rhs: [ "Unlock", "RUnlock" ] + + # Causes an error when an If statement that checks an error variable doesn't + # cuddle with the assignment of that variable. + force-err-cuddling: false + + # When force-err-cuddling is enabled this is a list of names + # used for error variables to check for in the conditional. + error-variable-names: [ "err" ] + + # Causes an error if a short declaration (:=) cuddles with anything other than + # another short declaration. + # This logic overrides force-err-cuddling among others. + force-short-decl-cuddling: false linters: - enable-all: true + # Disable all linters. + # Default: false disable-all: false + # Enable specific linter + # https://golangci-lint.run/usage/linters/#enabled-by-default + enable: [] + # Enable all available linters. + # Default: false + enable-all: true + # Disable specific linter + # https://golangci-lint.run/usage/linters/#disabled-by-default disable: - - exhaustive - - cyclop - - depguard - - gci - - golint - - err113 - - nlreturn - - revive - - perfsprint # FIXME - - ireturn - - dupl - varnamelen - - stylecheck - - exhaustivestruct # FIXME - - exhaustruct # FIXME - wrapcheck + - importas - wsl + - execinquery + - revive - gomnd - - forcetypeassert # FIXME - - godot - - nilnil # FIXME + - mnd + - exhaustruct + - ireturn + - err113 + - gochecknoglobals + - dupl - nonamedreturns - - maintidx - funlen - - gochecknoglobals - - gocognit - - nosnakecase - - maligned # FIXME - - mnd - - execinquery + - maintidx + - exhaustive + - nilnil + - prealloc + - forcetypeassert + + # Enable presets. + # https://golangci-lint.run/usage/linters + # Default: [] + presets: [] + # Enable only fast linters from enabled linters set (first run won't be fast) + # Default: false fast: false + issues: - # List of regexps of issue texts to exclude, empty list by default. - # But independently from this option we use default exclude patterns, - # it can be disabled by `exclude-use-default: false`. To list all - # excluded by default patterns execute `golangci-lint run --help` - exclude: [ ] + # List of regexps of issue texts to exclude. + # + # But independently of this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. + # To list all excluded by default patterns execute `golangci-lint run --help` + # + # Default: https://golangci-lint.run/usage/false-positives/#default-exclusions + exclude: [] # Excluding configuration per-path, per-linter, per-text and per-source exclude-rules: # Exclude some linters from running on tests files. - path: _test\.go linters: - - bodyclose - - forcetypeassert + - gocyclo + - errcheck - dupl - - gomnd - - gochecknoglobals - - goconst - - funlen - - noctx - - # disable errorlint for exact ErrStopped error, used in main.go to determine when app is manually stopped - - path: 'commands/.*\.go' - linters: - - errorlint - source: 'ErrStopped' + - gosec - - path: 'commands/.*\.go' + # Run some linter only for test files by excluding its issues for everything else. + - path-except: _test\.go linters: - - funlen - - gochecknoglobals + - forbidigo - - path: 'main\.go' - linters: - - funlen - - gochecknoglobals - - - path: _test\.go + # Exclude known linters from partially hard-vendored code, + # which is impossible to exclude via `nolint` comments. + # `/` will be replaced by current OS file path separator to properly work on Windows. + - path: internal/hmac/ + text: "weak cryptographic primitive" linters: - gosec - # G107: Potential HTTP request made with variable url - # We need to suppress it in tests for helper functions purpose. - text: G107 - - path: 'hash/md5\.go' - linters: - - gosec - # G501: Import blocklist: crypto/md5 - # G401: Detect the usage of DES, RC4, MD5 or SHA1 - text: (G501|G401) + # Exclude some `staticcheck` messages. + - linters: + - staticcheck + text: "SA9003:" + + # Exclude `lll` issues for long lines with `go:generate`. + - linters: + - lll + source: "^//go:generate " # Independently of option `exclude` we use default exclude patterns, - # it can be disabled by this option. To list all - # excluded by default patterns execute `golangci-lint run --help`. - # Default value for this option is true. + # it can be disabled by this option. + # To list all excluded by default patterns execute `golangci-lint run --help`. + # Default: true exclude-use-default: false - # The default value is false. If set to true exclude and exclude-rules - # regular expressions become case sensitive. + # If set to true, `exclude` and `exclude-rules` regular expressions become case-sensitive. + # Default: false exclude-case-sensitive: false - # The list of ids of default excludes to include or disable. By default it's empty. - include: [ ] + # Which dirs to exclude: issues from them won't be reported. + # Can use regexp here: `generated.*`, regexp is applied on full path, + # including the path prefix if one is set. + # Default dirs are skipped independently of this option's value (see exclude-dirs-use-default). + # "/" will be replaced by current OS file path separator to properly work on Windows. + # Default: [] + exclude-dirs: [] + + # Enables exclude of directories: + # - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + # Default: true + exclude-dirs-use-default: true - # Maximum issues count per one linter. Set to 0 to disable. Default is 50. - max-issues-per-linter: 0 + # Which files to exclude: they will be analyzed, but issues from them won't be reported. + # There is no need to include all autogenerated files, + # we confidently recognize autogenerated files. + # If it's not, please let us know. + # "/" will be replaced by current OS file path separator to properly work on Windows. + # Default: [] + exclude-files: [] - # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. - max-same-issues: 0 + # Mode of the generated files analysis. + # + # - `strict`: sources are excluded by following strictly the Go generated file convention. + # Source files that have lines matching only the following regular expression will be excluded: `^// Code generated .* DO NOT EDIT\.$` + # This line must appear before the first non-comment, non-blank text in the file. + # https://go.dev/s/generatedcode + # - `lax`: sources are excluded if they contain lines `autogenerated file`, `code generated`, `do not edit`, etc. + # - `disable`: disable the generated files exclusion. + # + # Default: lax + exclude-generated: strict + + # The list of ids of default excludes to include or disable. + # https://golangci-lint.run/usage/false-positives/#default-exclusions + # Default: [] + include: + - EXC0001 + - EXC0002 + - EXC0003 + - EXC0004 + - EXC0005 + - EXC0006 + - EXC0007 + - EXC0008 + - EXC0009 + - EXC0010 + - EXC0011 + - EXC0012 + - EXC0013 + - EXC0014 + - EXC0015 + + # Maximum issues count per one linter. + # Set to 0 to disable. + # Default: 50 + max-issues-per-linter: 50 + + # Maximum count of issues with the same text. + # Set to 0 to disable. + # Default: 3 + max-same-issues: 3 # Show only new issues: if there are unstaged changes or untracked files, # only those changes are analyzed, else only changes in HEAD~ are analyzed. - # It's a super-useful option for integration of golangci-lint into existing - # large codebase. It's not practical to fix all existing issues at the moment - # of integration: much better don't allow issues in new code. - # Default is false. + # It's a super-useful option for integration of golangci-lint into existing large codebase. + # It's not practical to fix all existing issues at the moment of integration: + # much better don't allow issues in new code. + # + # Default: false new: false - # Show only new issues created after git revision `REV` + # Show only new issues created after git revision `REV`. + # Default: "" new-from-rev: "" # Show only new issues created in git patch with set file path. + # Default: "" new-from-patch: "" - # Fix found issues (if it's supported by the linter) + # Fix found issues (if it's supported by the linter). + # Default: false fix: false + # Show issues in any part of update files (requires new-from-rev or new-from-patch). + # Default: false + whole-files: false + severity: - # Default value is empty string. - # Set the default severity for issues. If severity rules are defined and the issues - # do not match or no severity is provided to the rule this will be the default - # severity applied. Severities should match the supported severity names of the - # selected out format. + # Set the default severity for issues. + # + # If severity rules are defined and the issues do not match or no severity is provided to the rule + # this will be the default severity applied. + # Severities should match the supported severity names of the selected out format. # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity - # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity - # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#SeverityLevel + # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + # - TeamCity: https://www.jetbrains.com/help/teamcity/service-messages.html#Inspection+Instance + # + # `@linter` can be used as severity value to keep the severity from linters (e.g. revive, gosec, ...) + # + # Default: "" default-severity: error - # The default value is false. - # If set to true severity-rules regular expressions become case sensitive. + # If set to true `severity-rules` regular expressions become case-sensitive. + # Default: false case-sensitive: false + + # When a list of severity rules are provided, severity information will be added to lint issues. + # Severity rules have the same filtering capability as exclude rules + # except you are allowed to specify one matcher per severity rule. + # + # `@linter` can be used as severity value to keep the severity from linters (e.g. revive, gosec, ...) + # + # Only affects out formats that support setting severity information. + # + # Default: [] + rules: [] diff --git a/cmd/shell/main.go b/cmd/shell/main.go index 3559a87..b857a14 100644 --- a/cmd/shell/main.go +++ b/cmd/shell/main.go @@ -22,6 +22,7 @@ func main() { sqlParser := engine.ParseFn(func(sql string) (ast.Node, error) { lx := lexer.New(sql) pr := parser.New(lx) + return pr.Parse() }) diff --git a/internal/shell/shell.go b/internal/shell/shell.go index ff2682f..bca6139 100644 --- a/internal/shell/shell.go +++ b/internal/shell/shell.go @@ -259,11 +259,13 @@ Commands: \help Show help \quit Quit ` + return help } func (s *Shell) quit() string { close(s.closeCh) + return "Bye!\n" } diff --git a/internal/sql/engine/engine_test.go b/internal/sql/engine/engine_test.go index bec4791..bebbc34 100644 --- a/internal/sql/engine/engine_test.go +++ b/internal/sql/engine/engine_test.go @@ -1,7 +1,7 @@ package engine_test import ( - "fmt" + "errors" "testing" "github.com/stretchr/testify/assert" @@ -103,7 +103,7 @@ func TestEngine_Query(t *testing.T) { input := "select true" database := "playground" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") parser := NewMockParser(ctrl) planner := NewMockPlanner(ctrl) @@ -125,7 +125,7 @@ func TestEngine_Query(t *testing.T) { input := "select true" database := "playground" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") astNode := &ast.SelectStatement{ Result: []ast.ResultStatement{ { @@ -159,7 +159,7 @@ func TestEngine_Query(t *testing.T) { input := "select true" database := "playground" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") astNode := &ast.SelectStatement{ Result: []ast.ResultStatement{ { diff --git a/internal/sql/expr/binary_test.go b/internal/sql/expr/binary_test.go index 0b487b2..0f44527 100644 --- a/internal/sql/expr/binary_test.go +++ b/internal/sql/expr/binary_test.go @@ -1,6 +1,7 @@ package expr_test import ( + "errors" "fmt" "testing" @@ -909,7 +910,7 @@ func TestBinary_Eval(t *testing.T) { Right: rightNode, } - expected := fmt.Errorf("unexpected error") + expected := errors.New("unexpected error") leftNode.EXPECT().Eval(nil).Return(nil, expected) value, err := equal.Eval(nil) @@ -932,7 +933,7 @@ func TestBinary_Eval(t *testing.T) { Right: rightNode, } - expected := fmt.Errorf("unexpected error") + expected := errors.New("unexpected error") leftValue := sql.NewMockValue(ctrl) gomock.InOrder( diff --git a/internal/sql/expr/column.go b/internal/sql/expr/column.go index 99c4e0f..cdb2df6 100644 --- a/internal/sql/expr/column.go +++ b/internal/sql/expr/column.go @@ -1,6 +1,7 @@ package expr import ( + "errors" "fmt" "github.com/i-sevostyanov/NanoDB/internal/sql" @@ -17,7 +18,7 @@ func (c Column) String() string { func (c Column) Eval(row sql.Row) (sql.Value, error) { if len(row) == 0 { - return nil, fmt.Errorf("empty row") + return nil, errors.New("empty row") } if int(c.Position) > len(row) { diff --git a/internal/sql/expr/expression.go b/internal/sql/expr/expression.go index 35b0151..46abfa7 100644 --- a/internal/sql/expr/expression.go +++ b/internal/sql/expr/expression.go @@ -1,6 +1,7 @@ package expr import ( + "errors" "fmt" "github.com/i-sevostyanov/NanoDB/internal/sql" @@ -37,7 +38,7 @@ func walk(node ast.Expression, scheme sql.Scheme) (Node, error) { func columnExpr(expr *ast.IdentExpr, scheme sql.Scheme) (Node, error) { if scheme == nil { - return nil, fmt.Errorf("schema not provided") + return nil, errors.New("schema not provided") } definition, ok := scheme[expr.Name] diff --git a/internal/sql/expr/logical/and.go b/internal/sql/expr/logical/and.go index 2b3ae02..4e51e3c 100644 --- a/internal/sql/expr/logical/and.go +++ b/internal/sql/expr/logical/and.go @@ -1,6 +1,7 @@ package logical import ( + "errors" "fmt" "github.com/i-sevostyanov/NanoDB/internal/sql" @@ -12,8 +13,15 @@ func And(left, right sql.Value) (sql.Value, error) { return nil, fmt.Errorf("and: unsupported operation for %T and %T values", left.Raw(), right.Raw()) } - lvalue := left.Raw().(bool) - rvalue := right.Raw().(bool) + lvalue, ok := left.Raw().(bool) + if !ok { + return nil, errors.New("and: left operand should be bool") + } + + rvalue, ok := right.Raw().(bool) + if !ok { + return nil, errors.New("and: right operand should be bool") + } return datatype.NewBoolean(lvalue && rvalue), nil } diff --git a/internal/sql/expr/logical/or.go b/internal/sql/expr/logical/or.go index 14b7a17..4fc90c1 100644 --- a/internal/sql/expr/logical/or.go +++ b/internal/sql/expr/logical/or.go @@ -1,6 +1,7 @@ package logical import ( + "errors" "fmt" "github.com/i-sevostyanov/NanoDB/internal/sql" @@ -12,8 +13,15 @@ func Or(left, right sql.Value) (sql.Value, error) { return nil, fmt.Errorf("and: unsupported operation for %T and %T values", left.Raw(), right.Raw()) } - lvalue := left.Raw().(bool) - rvalue := right.Raw().(bool) + lvalue, ok := left.Raw().(bool) + if !ok { + return nil, errors.New("and: left operand should be bool") + } + + rvalue, ok := right.Raw().(bool) + if !ok { + return nil, errors.New("and: right operand should be bool") + } return datatype.NewBoolean(lvalue || rvalue), nil } diff --git a/internal/sql/expr/math/add.go b/internal/sql/expr/math/add.go index 0d4067b..856a102 100644 --- a/internal/sql/expr/math/add.go +++ b/internal/sql/expr/math/add.go @@ -17,15 +17,19 @@ func Add(left, right sql.Value) (sql.Value, error) { case sql.Float: lvalue := left.Raw().(float64) rvalue := right.Raw().(float64) + return datatype.NewFloat(lvalue + rvalue), nil case sql.Integer: lvalue := left.Raw().(int64) rvalue := right.Raw().(int64) + return datatype.NewInteger(lvalue + rvalue), nil case sql.Text: lvalue := left.Raw().(string) rvalue := right.Raw().(string) + return datatype.NewText(lvalue + rvalue), nil + default: } } diff --git a/internal/sql/expr/math/div.go b/internal/sql/expr/math/div.go index cb20e6a..2f32b4c 100644 --- a/internal/sql/expr/math/div.go +++ b/internal/sql/expr/math/div.go @@ -1,6 +1,7 @@ package math import ( + "errors" "fmt" "github.com/i-sevostyanov/NanoDB/internal/sql" @@ -19,7 +20,7 @@ func Div(left, right sql.Value) (sql.Value, error) { rvalue := right.Raw().(float64) if rvalue == 0 { - return nil, fmt.Errorf("division by zero") + return nil, errors.New("division by zero") } return datatype.NewFloat(lvalue / rvalue), nil @@ -28,10 +29,11 @@ func Div(left, right sql.Value) (sql.Value, error) { rvalue := right.Raw().(int64) if rvalue == 0 { - return nil, fmt.Errorf("division by zero") + return nil, errors.New("division by zero") } return datatype.NewInteger(lvalue / rvalue), nil + default: } } @@ -40,7 +42,7 @@ func Div(left, right sql.Value) (sql.Value, error) { rvalue := right.Raw().(float64) if rvalue == 0 { - return nil, fmt.Errorf("division by zero") + return nil, errors.New("division by zero") } return datatype.NewFloat(lvalue / rvalue), nil @@ -51,7 +53,7 @@ func Div(left, right sql.Value) (sql.Value, error) { rvalue := float64(right.Raw().(int64)) if rvalue == 0 { - return nil, fmt.Errorf("division by zero") + return nil, errors.New("division by zero") } return datatype.NewFloat(lvalue / rvalue), nil diff --git a/internal/sql/expr/math/mod.go b/internal/sql/expr/math/mod.go index 5ec1a17..d55a113 100644 --- a/internal/sql/expr/math/mod.go +++ b/internal/sql/expr/math/mod.go @@ -1,6 +1,7 @@ package math import ( + "errors" "fmt" "math" @@ -20,7 +21,7 @@ func Mod(left, right sql.Value) (sql.Value, error) { rvalue := right.Raw().(float64) if rvalue == 0 { - return nil, fmt.Errorf("division by zero") + return nil, errors.New("division by zero") } return datatype.NewFloat(math.Mod(lvalue, rvalue)), nil @@ -29,10 +30,11 @@ func Mod(left, right sql.Value) (sql.Value, error) { rvalue := right.Raw().(int64) if rvalue == 0 { - return nil, fmt.Errorf("division by zero") + return nil, errors.New("division by zero") } return datatype.NewInteger(lvalue % rvalue), nil + default: } } @@ -41,7 +43,7 @@ func Mod(left, right sql.Value) (sql.Value, error) { rvalue := right.Raw().(float64) if rvalue == 0 { - return nil, fmt.Errorf("division by zero") + return nil, errors.New("division by zero") } return datatype.NewFloat(math.Mod(lvalue, rvalue)), nil @@ -52,7 +54,7 @@ func Mod(left, right sql.Value) (sql.Value, error) { rvalue := float64(right.Raw().(int64)) if rvalue == 0 { - return nil, fmt.Errorf("division by zero") + return nil, errors.New("division by zero") } return datatype.NewFloat(math.Mod(lvalue, rvalue)), nil diff --git a/internal/sql/expr/math/mul.go b/internal/sql/expr/math/mul.go index c73599e..e0387de 100644 --- a/internal/sql/expr/math/mul.go +++ b/internal/sql/expr/math/mul.go @@ -17,11 +17,14 @@ func Mul(left, right sql.Value) (sql.Value, error) { case sql.Float: lvalue := left.Raw().(float64) rvalue := right.Raw().(float64) + return datatype.NewFloat(lvalue * rvalue), nil case sql.Integer: lvalue := left.Raw().(int64) rvalue := right.Raw().(int64) + return datatype.NewInteger(lvalue * rvalue), nil + default: } } diff --git a/internal/sql/expr/math/pow.go b/internal/sql/expr/math/pow.go index 09d1feb..3c5caf1 100644 --- a/internal/sql/expr/math/pow.go +++ b/internal/sql/expr/math/pow.go @@ -18,11 +18,14 @@ func Pow(left, right sql.Value) (sql.Value, error) { case sql.Float: lvalue := left.Raw().(float64) rvalue := right.Raw().(float64) + return datatype.NewFloat(math.Pow(lvalue, rvalue)), nil case sql.Integer: lvalue := left.Raw().(int64) rvalue := right.Raw().(int64) + return datatype.NewFloat(math.Pow(float64(lvalue), float64(rvalue))), nil + default: } } diff --git a/internal/sql/expr/math/sub.go b/internal/sql/expr/math/sub.go index f3dd076..150858d 100644 --- a/internal/sql/expr/math/sub.go +++ b/internal/sql/expr/math/sub.go @@ -17,11 +17,14 @@ func Sub(left, right sql.Value) (sql.Value, error) { case sql.Float: lvalue := left.Raw().(float64) rvalue := right.Raw().(float64) + return datatype.NewFloat(lvalue - rvalue), nil case sql.Integer: lvalue := left.Raw().(int64) rvalue := right.Raw().(int64) + return datatype.NewInteger(lvalue - rvalue), nil + default: } } diff --git a/internal/sql/expr/math/unary_minus.go b/internal/sql/expr/math/unary_minus.go index ad86765..74c3bdd 100644 --- a/internal/sql/expr/math/unary_minus.go +++ b/internal/sql/expr/math/unary_minus.go @@ -11,9 +11,11 @@ func UnaryMinus(value sql.Value) (sql.Value, error) { switch value.DataType() { case sql.Float: v := value.Raw().(float64) + return datatype.NewFloat(-v), nil case sql.Integer: v := value.Raw().(int64) + return datatype.NewInteger(-v), nil default: return nil, fmt.Errorf("unary-minus: unsupported operand %T", value.Raw()) diff --git a/internal/sql/expr/math/unary_plus.go b/internal/sql/expr/math/unary_plus.go index 787394d..1181b10 100644 --- a/internal/sql/expr/math/unary_plus.go +++ b/internal/sql/expr/math/unary_plus.go @@ -11,9 +11,11 @@ func UnaryPlus(value sql.Value) (sql.Value, error) { switch value.DataType() { case sql.Float: v := value.Raw().(float64) + return datatype.NewFloat(v), nil case sql.Integer: v := value.Raw().(int64) + return datatype.NewInteger(v), nil default: return nil, fmt.Errorf("unary-plus: unsupported operand %T", value.Raw()) diff --git a/internal/sql/expr/unary_test.go b/internal/sql/expr/unary_test.go index 0f34b3a..06be91d 100644 --- a/internal/sql/expr/unary_test.go +++ b/internal/sql/expr/unary_test.go @@ -1,7 +1,7 @@ package expr_test import ( - "fmt" + "errors" "math" "testing" @@ -135,7 +135,7 @@ func TestUnary_Eval(t *testing.T) { defer ctrl.Finish() operand := expr.NewMockNode(ctrl) - expected := fmt.Errorf("something went wrong") + expected := errors.New("something went wrong") unaryExpr := expr.Unary{ Operator: expr.UnaryMinus, Operand: operand, diff --git a/internal/sql/parsing/ast/ast.go b/internal/sql/parsing/ast/ast.go index 2b7debb..141b5be 100644 --- a/internal/sql/parsing/ast/ast.go +++ b/internal/sql/parsing/ast/ast.go @@ -6,7 +6,7 @@ import ( ) // Node represents AST-node of the syntax tree for SQL query. -type Node interface{} +type Node any // Statement represents syntax tree node of SQL statement (like: SELECT). type Statement interface { diff --git a/internal/sql/parsing/lexer/lexer.go b/internal/sql/parsing/lexer/lexer.go index 7fcf904..728a102 100644 --- a/internal/sql/parsing/lexer/lexer.go +++ b/internal/sql/parsing/lexer/lexer.go @@ -68,6 +68,7 @@ func (l *Lexer) NextToken() token.Token { case '<': if next := l.peek(); next == '=' { l.next() + return token.New(token.LessThanOrEqual, l.offset) } @@ -75,6 +76,7 @@ func (l *Lexer) NextToken() token.Token { case '>': if next := l.peek(); next == '=' { l.next() + return token.New(token.GreaterThanOrEqual, l.offset) } @@ -82,6 +84,7 @@ func (l *Lexer) NextToken() token.Token { case '!': if next := l.peek(); next == '=' { l.next() + return token.New(token.NotEqual, l.offset) } diff --git a/internal/sql/parsing/parser/parser.go b/internal/sql/parsing/parser/parser.go index 13125d3..fb46fc4 100644 --- a/internal/sql/parsing/parser/parser.go +++ b/internal/sql/parsing/parser/parser.go @@ -2,6 +2,7 @@ package parser import ( + "errors" "fmt" "github.com/i-sevostyanov/NanoDB/internal/sql/parsing/ast" @@ -29,9 +30,9 @@ func New(lx Lexer) *Parser { } } -// Parse parses the sql and returns a statement. +// Parse parses the SQL and returns a statement. func (p *Parser) Parse() (ast.Statement, error) { - // For simplicity, we parse one statement at a time but in the next release, + // For simplicity, we parse one statement at a time, but in the next release, // we should implement parsing multiple statements separated semicolon. return p.parseStatement() } @@ -70,9 +71,11 @@ func (p *Parser) parseCreateStatement() (ast.Statement, error) { switch p.token.Type { case token.Database: p.nextToken() + return p.parseCreateDatabaseStatement() case token.Table: p.nextToken() + return p.parseCreateTableStatement() default: return nil, fmt.Errorf("unexpected keyword after CREATE statement %q", p.token.Type) @@ -85,9 +88,11 @@ func (p *Parser) parseDropStatement() (ast.Statement, error) { switch p.token.Type { case token.Database: p.nextToken() + return p.parseDropDatabaseStatement() case token.Table: p.nextToken() + return p.parseDropTableStatement() default: return nil, fmt.Errorf("unexpected keyword after DROP statement %q", p.token.Type) @@ -325,14 +330,15 @@ func (p *Parser) parseColumnType() (token.Type, error) { p.nextToken() return columnType, nil + default: + return token.Illegal, fmt.Errorf("unexpected column type: %q", p.token.Type) } - - return token.Illegal, fmt.Errorf("unexpected column type: %q", p.token.Type) } func (p *Parser) parseColumnNullable() (bool, error) { if p.token.Type == token.Null { p.nextToken() + return true, nil } @@ -427,7 +433,7 @@ func (p *Parser) parseResultStatement() ([]ast.ResultStatement, error) { } if len(results) == 0 { - return nil, fmt.Errorf("no columns specified") + return nil, errors.New("no columns specified") } return results, nil @@ -517,12 +523,14 @@ func (p *Parser) parseOrderByStatement() (*ast.OrderByStatement, error) { return nil, err } - direction := token.Asc + var direction token.Type switch p.token.Type { case token.Asc, token.Desc: direction = p.token.Type p.nextToken() + default: + direction = token.Asc } order := ast.OrderByStatement{ @@ -660,6 +668,7 @@ func (p *Parser) parseSetStatement() ([]ast.SetStatement, error) { if p.peekToken.Type == token.EOF || p.peekToken.Type == token.Where { p.nextToken() + break } diff --git a/internal/sql/planning/plan/create_test.go b/internal/sql/planning/plan/create_test.go index 4cb3d51..58182e3 100644 --- a/internal/sql/planning/plan/create_test.go +++ b/internal/sql/planning/plan/create_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -53,7 +53,7 @@ func TestCreateDatabase_RowIter(t *testing.T) { defer ctrl.Finish() name := "test" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") creator := NewMockDatabaseCreator(ctrl) creator.EXPECT().CreateDatabase(name).Return(nil, expectedErr) @@ -108,7 +108,7 @@ func TestCreateTable_RowIter(t *testing.T) { name := "test" scheme := sql.Scheme{} - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") creator := NewMockTableCreator(ctrl) creator.EXPECT().CreateTable(name, scheme).Return(nil, expectedErr) diff --git a/internal/sql/planning/plan/delete_test.go b/internal/sql/planning/plan/delete_test.go index fdff5dd..9a8675d 100644 --- a/internal/sql/planning/plan/delete_test.go +++ b/internal/sql/planning/plan/delete_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -82,7 +82,7 @@ func TestDelete_RowIter(t *testing.T) { defer ctrl.Finish() pkIndex := uint8(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) deleter := NewMockRowDeleter(ctrl) @@ -102,7 +102,7 @@ func TestDelete_RowIter(t *testing.T) { defer ctrl.Finish() pkIndex := uint8(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) rowIter := sql.NewMockRowIter(ctrl) @@ -133,7 +133,7 @@ func TestDelete_RowIter(t *testing.T) { defer ctrl.Finish() pkIndex := uint8(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") row := sql.Row{ datatype.NewInteger(1), diff --git a/internal/sql/planning/plan/drop_test.go b/internal/sql/planning/plan/drop_test.go index e2c59e1..d937e92 100644 --- a/internal/sql/planning/plan/drop_test.go +++ b/internal/sql/planning/plan/drop_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -52,7 +52,7 @@ func TestDropDatabase_RowIter(t *testing.T) { defer ctrl.Finish() name := "test" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") dropper := NewMockDatabaseDropper(ctrl) dropper.EXPECT().DropDatabase(name).Return(expectedErr) @@ -106,7 +106,7 @@ func TestDropTable_RowIter(t *testing.T) { defer ctrl.Finish() name := "test" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") dropper := NewMockTableDropper(ctrl) dropper.EXPECT().DropTable(name).Return(expectedErr) diff --git a/internal/sql/planning/plan/filter_test.go b/internal/sql/planning/plan/filter_test.go index cbe807a..0eef624 100644 --- a/internal/sql/planning/plan/filter_test.go +++ b/internal/sql/planning/plan/filter_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -93,7 +93,7 @@ func TestFilter_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") cond := expr.NewMockNode(ctrl) child := plan.NewMockNode(ctrl) @@ -112,7 +112,7 @@ func TestFilter_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") cond := expr.NewMockNode(ctrl) child := plan.NewMockNode(ctrl) @@ -147,7 +147,7 @@ func TestFilter_RowIter(t *testing.T) { child := plan.NewMockNode(ctrl) rowIter := sql.NewMockRowIter(ctrl) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") row := sql.Row{ datatype.NewInteger(1), datatype.NewText("Max"), diff --git a/internal/sql/planning/plan/insert_test.go b/internal/sql/planning/plan/insert_test.go index 50f22a9..5a04d70 100644 --- a/internal/sql/planning/plan/insert_test.go +++ b/internal/sql/planning/plan/insert_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -65,7 +65,7 @@ func TestInsert_RowIter(t *testing.T) { defer ctrl.Finish() key := int64(1) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") row := sql.Row{ datatype.NewInteger(key), datatype.NewText("Max"), diff --git a/internal/sql/planning/plan/limit_test.go b/internal/sql/planning/plan/limit_test.go index cc18d57..ef25e7a 100644 --- a/internal/sql/planning/plan/limit_test.go +++ b/internal/sql/planning/plan/limit_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -123,7 +123,7 @@ func TestLimit_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("somethig went wtrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) child.EXPECT().RowIter().Return(nil, expectedErr) @@ -140,7 +140,7 @@ func TestLimit_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("somethig went wtrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) rowIter := sql.NewMockRowIter(ctrl) diff --git a/internal/sql/planning/plan/offset_test.go b/internal/sql/planning/plan/offset_test.go index 8a13d13..ae30e53 100644 --- a/internal/sql/planning/plan/offset_test.go +++ b/internal/sql/planning/plan/offset_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -116,7 +116,7 @@ func TestOffset_RowIter(t *testing.T) { defer ctrl.Finish() N := int64(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) child.EXPECT().RowIter().Return(nil, expectedErr) @@ -161,7 +161,7 @@ func TestOffset_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) rowIter := sql.NewMockRowIter(ctrl) @@ -191,7 +191,7 @@ func TestOffset_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) rowIter := sql.NewMockRowIter(ctrl) diff --git a/internal/sql/planning/plan/project_test.go b/internal/sql/planning/plan/project_test.go index 8e07af7..f099fcb 100644 --- a/internal/sql/planning/plan/project_test.go +++ b/internal/sql/planning/plan/project_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -161,7 +161,7 @@ func TestProject_RowIter(t *testing.T) { {datatype.NewInteger(2), datatype.NewText("Frank"), datatype.NewFloat(2200)}, } - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") id := expr.NewMockNode(ctrl) name := expr.NewMockNode(ctrl) @@ -199,7 +199,7 @@ func TestProject_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") id := expr.NewMockNode(ctrl) name := expr.NewMockNode(ctrl) @@ -228,7 +228,7 @@ func TestProject_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") id := expr.NewMockNode(ctrl) name := expr.NewMockNode(ctrl) diff --git a/internal/sql/planning/plan/scan_test.go b/internal/sql/planning/plan/scan_test.go index f719199..b2b6fe4 100644 --- a/internal/sql/planning/plan/scan_test.go +++ b/internal/sql/planning/plan/scan_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "testing" "github.com/stretchr/testify/assert" @@ -78,7 +78,7 @@ func TestScan_RowIter(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") table := sql.NewMockTable(ctrl) table.EXPECT().Scan().Return(nil, expectedErr) diff --git a/internal/sql/planning/plan/sort.go b/internal/sql/planning/plan/sort.go index f1c6d61..ccd5649 100644 --- a/internal/sql/planning/plan/sort.go +++ b/internal/sql/planning/plan/sort.go @@ -78,6 +78,7 @@ func (i *sortIter) Next() (sql.Row, error) { func (i *sortIter) Close() error { i.rows = nil + return i.iter.Close() } diff --git a/internal/sql/planning/plan/sort_test.go b/internal/sql/planning/plan/sort_test.go index 1aa8bff..ecacb87 100644 --- a/internal/sql/planning/plan/sort_test.go +++ b/internal/sql/planning/plan/sort_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "math" "testing" @@ -904,7 +904,7 @@ func TestSort_RowIter(t *testing.T) { order := plan.Descending columnPos := uint8(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) child.EXPECT().RowIter().Return(nil, expectedErr) @@ -947,7 +947,7 @@ func TestSort_RowIter(t *testing.T) { order := plan.Descending columnPos := uint8(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") child := plan.NewMockNode(ctrl) rowIter := sql.NewMockRowIter(ctrl) diff --git a/internal/sql/planning/plan/update_test.go b/internal/sql/planning/plan/update_test.go index 54eaa53..8e4f076 100644 --- a/internal/sql/planning/plan/update_test.go +++ b/internal/sql/planning/plan/update_test.go @@ -1,7 +1,7 @@ package plan_test import ( - "fmt" + "errors" "io" "testing" @@ -109,7 +109,7 @@ func TestUpdate_RowIter(t *testing.T) { t.Parallel() pkIndex := uint8(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") columns := map[uint8]expr.Node{} ctrl := gomock.NewController(t) @@ -130,7 +130,7 @@ func TestUpdate_RowIter(t *testing.T) { t.Parallel() pkIndex := uint8(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") columns := map[uint8]expr.Node{} ctrl := gomock.NewController(t) @@ -157,7 +157,7 @@ func TestUpdate_RowIter(t *testing.T) { t.Parallel() pkIndex := uint8(0) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") row := sql.Row{ datatype.NewInteger(1), datatype.NewText("Max"), @@ -241,7 +241,7 @@ func TestUpdate_RowIter(t *testing.T) { child := plan.NewMockNode(ctrl) rowIter := sql.NewMockRowIter(ctrl) - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") key := int64(1) pkIndex := uint8(0) columns := map[uint8]expr.Node{ diff --git a/internal/sql/planning/planner/planner.go b/internal/sql/planning/planner/planner.go index fbbd587..8c25135 100644 --- a/internal/sql/planning/planner/planner.go +++ b/internal/sql/planning/planner/planner.go @@ -1,6 +1,7 @@ package planner import ( + "errors" "fmt" "github.com/i-sevostyanov/NanoDB/internal/sql" @@ -102,7 +103,7 @@ func (p *Planner) planInsert(database string, stmt *ast.InsertStatement) (plan.N } if len(stmt.Columns) != len(stmt.Values) { - return nil, fmt.Errorf("number of expressions should be equal to the number of columns") + return nil, errors.New("number of expressions should be equal to the number of columns") } var key int64 @@ -271,11 +272,11 @@ func (p *Planner) planTableScheme(columns []ast.Column) (sql.Scheme, error) { } if primaryKeys == 0 { - return nil, fmt.Errorf("primary key is required") + return nil, errors.New("primary key is required") } if primaryKeys > 1 { - return nil, fmt.Errorf("multiple primary keys are not allowed") + return nil, errors.New("multiple primary keys are not allowed") } return scheme, nil @@ -352,7 +353,7 @@ func (p *Planner) planProject(table sql.Table, stmt []ast.ResultStatement, child ) if len(stmt) == 0 { - return nil, fmt.Errorf("projections list should be not empty") + return nil, errors.New("projections list should be not empty") } if table != nil { @@ -373,7 +374,7 @@ func (p *Planner) planProjections(scheme sql.Scheme, stmt []ast.ResultStatement) switch stmt[i].Expr.(type) { case *ast.AsteriskExpr: if scheme == nil { - return nil, fmt.Errorf("table not specified") + return nil, errors.New("table not specified") } columns := make([]string, len(scheme)) @@ -412,7 +413,7 @@ func (p *Planner) planFilter(table sql.Table, stmt *ast.WhereStatement, child pl } if table == nil { - return nil, fmt.Errorf("table not specified") + return nil, errors.New("table not specified") } cond, err := expr.New(stmt.Expr, table.Scheme()) @@ -429,7 +430,7 @@ func (p *Planner) planSort(table sql.Table, stmt *ast.OrderByStatement, child pl } if table == nil { - return nil, fmt.Errorf("table not specified") + return nil, errors.New("table not specified") } column, ok := table.Scheme()[stmt.Column] @@ -468,11 +469,11 @@ func (p *Planner) planOffset(stmt *ast.OffsetStatement, child plan.Node) (plan.N n, ok := limit.Raw().(int64) if !ok { - return nil, fmt.Errorf("OFFSET expr must be integer type") + return nil, errors.New("OFFSET expr must be integer type") } if n < 0 { - return nil, fmt.Errorf("OFFSET must not be negative") + return nil, errors.New("OFFSET must not be negative") } return plan.NewOffset(n, child), nil @@ -495,11 +496,11 @@ func (p *Planner) planLimit(stmt *ast.LimitStatement, child plan.Node) (plan.Nod n, ok := limit.Raw().(int64) if !ok { - return nil, fmt.Errorf("LIMIT expr must be integer type") + return nil, errors.New("LIMIT expr must be integer type") } if n < 0 { - return nil, fmt.Errorf("LIMIT must not be negative") + return nil, errors.New("LIMIT must not be negative") } return plan.NewLimit(n, child), nil @@ -507,11 +508,11 @@ func (p *Planner) planLimit(stmt *ast.LimitStatement, child plan.Node) (plan.Nod func (p *Planner) getTable(databaseName, tableName string) (sql.Table, error) { if databaseName == "" { - return nil, fmt.Errorf("database not specified") + return nil, errors.New("database not specified") } if tableName == "" { - return nil, fmt.Errorf("table not specified") + return nil, errors.New("table not specified") } db, err := p.catalog.GetDatabase(databaseName) diff --git a/internal/sql/planning/planner/planner_test.go b/internal/sql/planning/planner/planner_test.go index 3dec142..4a82143 100644 --- a/internal/sql/planning/planner/planner_test.go +++ b/internal/sql/planning/planner/planner_test.go @@ -1,7 +1,7 @@ package planner_test import ( - "fmt" + "errors" "testing" "github.com/stretchr/testify/assert" @@ -27,7 +27,7 @@ func TestPlanner_CreateDatabase(t *testing.T) { defer ctrl.Finish() database := "users" - errDBNotExist := fmt.Errorf("databasse not exist") + errDBNotExist := errors.New("database not exist") catalog := sql.NewMockCatalog(ctrl) catalog.EXPECT().GetDatabase(database).Return(nil, errDBNotExist) @@ -96,7 +96,7 @@ func TestPlanner_DropDatabase(t *testing.T) { defer ctrl.Finish() database := "users" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") catalog := sql.NewMockCatalog(ctrl) catalog.EXPECT().GetDatabase(database).Return(nil, expectedErr) @@ -122,7 +122,7 @@ func TestPlanner_CreateTable(t *testing.T) { tableName := "users" databaseName := "playground" - errTableNotExist := fmt.Errorf("table not exist") + errTableNotExist := errors.New("table not exist") stmt := &ast.CreateTableStatement{ Table: tableName, @@ -220,7 +220,7 @@ func TestPlanner_CreateTable(t *testing.T) { tableName := "users" databaseName := "playground" - errTableNotExist := fmt.Errorf("table not exist") + errTableNotExist := errors.New("table not exist") stmt := &ast.CreateTableStatement{ Table: tableName, @@ -285,7 +285,7 @@ func TestPlanner_CreateTable(t *testing.T) { tableName := "users" databaseName := "playground" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") stmt := &ast.CreateTableStatement{ Table: tableName, @@ -369,7 +369,7 @@ func TestPlanner_CreateTable(t *testing.T) { tableName := "users" databaseName := "playground" - errTableNotExist := fmt.Errorf("table not exist") + errTableNotExist := errors.New("table not exist") stmt := &ast.CreateTableStatement{ Table: tableName, @@ -413,7 +413,7 @@ func TestPlanner_CreateTable(t *testing.T) { tableName := "users" databaseName := "playground" - errTableNotExist := fmt.Errorf("table not exist") + errTableNotExist := errors.New("table not exist") stmt := &ast.CreateTableStatement{ Table: tableName, @@ -457,7 +457,7 @@ func TestPlanner_CreateTable(t *testing.T) { tableName := "users" databaseName := "playground" - errTableNotExist := fmt.Errorf("table not exist") + errTableNotExist := errors.New("table not exist") stmt := &ast.CreateTableStatement{ Table: tableName, @@ -501,7 +501,7 @@ func TestPlanner_CreateTable(t *testing.T) { tableName := "users" databaseName := "playground" - errTableNotExist := fmt.Errorf("table not exist") + errTableNotExist := errors.New("table not exist") stmt := &ast.CreateTableStatement{ Table: tableName, @@ -574,7 +574,7 @@ func TestPlanner_DropTable(t *testing.T) { tableName := "users" databaseName := "playground" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") catalog := sql.NewMockCatalog(ctrl) catalog.EXPECT().GetDatabase(databaseName).Return(nil, expectedErr) @@ -596,7 +596,7 @@ func TestPlanner_DropTable(t *testing.T) { tableName := "users" databaseName := "playground" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") catalog := sql.NewMockCatalog(ctrl) database := sql.NewMockDatabase(ctrl) @@ -1459,7 +1459,7 @@ func TestPlanner_Delete(t *testing.T) { databaseName := "playground" tableName := "users" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") catalog := sql.NewMockCatalog(ctrl) catalog.EXPECT().GetDatabase(databaseName).Return(nil, expectedErr) @@ -1481,7 +1481,7 @@ func TestPlanner_Delete(t *testing.T) { databaseName := "playground" tableName := "users" - expectedErr := fmt.Errorf("something went wrong") + expectedErr := errors.New("something went wrong") catalog := sql.NewMockCatalog(ctrl) database := sql.NewMockDatabase(ctrl) diff --git a/internal/sql/rows.go b/internal/sql/rows.go index 8382fd9..0276d99 100644 --- a/internal/sql/rows.go +++ b/internal/sql/rows.go @@ -34,6 +34,7 @@ func (i *SliceRowsIter) Next() (Row, error) { func (i *SliceRowsIter) Close() error { i.rows = nil + return nil } diff --git a/internal/storage/memory/catalog.go b/internal/storage/memory/catalog.go index 369a80a..8cb843b 100644 --- a/internal/storage/memory/catalog.go +++ b/internal/storage/memory/catalog.go @@ -48,6 +48,7 @@ func (c *Catalog) CreateDatabase(name string) (sql.Database, error) { func (c *Catalog) DropDatabase(name string) error { if _, ok := c.databases[name]; ok { delete(c.databases, name) + return nil } diff --git a/internal/storage/memory/database.go b/internal/storage/memory/database.go index 138e5a6..b67f6ff 100644 --- a/internal/storage/memory/database.go +++ b/internal/storage/memory/database.go @@ -1,6 +1,7 @@ package memory import ( + "errors" "fmt" "github.com/i-sevostyanov/NanoDB/internal/sql" @@ -42,11 +43,11 @@ func (d *Database) GetTable(name string) (sql.Table, error) { func (d *Database) CreateTable(name string, scheme sql.Scheme) (sql.Table, error) { if _, ok := d.tables[name]; ok { - return nil, fmt.Errorf("table already exist") + return nil, errors.New("table already exist") } if len(scheme) == 0 { - return nil, fmt.Errorf("scheme should not be empty") + return nil, errors.New("scheme should not be empty") } table := NewTable(name, scheme) diff --git a/internal/storage/memory/table.go b/internal/storage/memory/table.go index 2efea44..fd08165 100644 --- a/internal/storage/memory/table.go +++ b/internal/storage/memory/table.go @@ -23,6 +23,7 @@ func NewTable(name string, scheme sql.Scheme) *Table { for column := range scheme { if scheme[column].PrimaryKey { primaryKey = scheme[column] + break } } @@ -95,6 +96,7 @@ func (t *Table) Delete(key int64) error { for index := range t.keys { if t.keys[index] == key { t.keys = append(t.keys[:index], t.keys[index+1:]...) + break } } @@ -132,5 +134,6 @@ func (i *iter) Next() (sql.Row, error) { func (i *iter) Close() error { i.rows = nil + return nil }