src/Definition/Teradata.php
File `Teradata.php` has 510 lines of code (exceeds 250 allowed). Consider refactoring.<?php declare(strict_types=1); namespace Keboola\Datatype\Definition; use Exception;use Keboola\Datatype\Definition\Exception\InvalidLengthException;use Keboola\Datatype\Definition\Exception\InvalidOptionException;use Keboola\Datatype\Definition\Exception\InvalidTypeException;use LogicException; /** * Class Teradata * * https://docs.teradata.com/r/Ri8d7iL59tIPr1FZNKPLMw/TQAE5zgqV8pvyhrySc7ZVg */The class Teradata has an overall complexity of 135 which is very high. The configured complexity threshold is 50.class Teradata extends Common{ //https://docs.teradata.com/r/Ri8d7iL59tIPr1FZNKPLMw/DlfSbsVEC48atCIcADa5IA /* numbers */ public const TYPE_BYTEINT = 'BYTEINT'; // -128 to 127, 1B, BYTEINT [ attributes [...] ] public const TYPE_BIGINT = 'BIGINT'; // 64bit signed, 7B, BIGINT [ attributes [...] ] public const TYPE_SMALLINT = 'SMALLINT'; // -32768 to 32767, 2B, SMALLINT [ attributes [...] ] public const TYPE_INTEGER = 'INTEGER'; // 32bit signed, 4B, { INTEGER | INT } [ attributes [...] ] public const TYPE_INT = 'INT'; // = INTEGER public const TYPE_DECIMAL = 'DECIMAL'; // fixed length up to 16B // DECIMAL [(n[,m])], { DECIMAL | DEC | NUMERIC } [ ( n [, m ] ) ] [ attributes [...] ], 12.4567 : n = 6; m = 4. // n: 1-38 ; m 0-n, default when no n nor m -> DECIMAL(5, 0)., default when n is specified -> DECIMAL(n, 0). public const TYPE_NUMERIC = 'NUMERIC'; // = DECIMAL public const TYPE_DEC = 'DEC'; // = DECIMAL public const TYPE_FLOAT = 'FLOAT'; // 8B, { FLOAT | REAL | DOUBLE PRECISION } [ attributes [...] ] public const TYPE_DOUBLE_PRECISION = 'DOUBLE PRECISION'; // = FLOAT public const TYPE_REAL = 'REAL'; // = FLOAT public const TYPE_NUMBER = 'NUMBER'; // 1-20B, NUMBER(n[,m]) / NUMBER[(*[,m])], as DECIMAL but variable-length // n: 1-38 ; m 0-n, default when no n nor m -> DECIMAL(5, 0)., default when n is specified DECIMAL(n, 0). /* Byte */ public const TYPE_BYTE = 'BYTE'; // BYTE [ ( n ) ] [ attributes [...] ]; n Max 64000 Bytes; fixed length public const TYPE_VARBYTE = 'VARBYTE'; // VARBYTE ( n ) [ attributes [...] ]; n Max 64000 Bytes; VARIABLE length public const TYPE_BLOB = 'BLOB'; // { BINARY LARGE OBJECT | BLOB } // [ ( n [ K | M | G ] ) ] // [ attribute [...] ] // n - amount of // Bytes - no unit // K - K - max 2047937 // M - M - max 1999 // G - G - 1 only public const TYPE_BINARY_LARGE_OBJECT = 'BINARY LARGE OBJECT'; /* DateTime */ public const TYPE_DATE = 'DATE'; // DATE [ attributes [...] ] // TIME [ ( n ) ] [ attributes [...] ]; // n = A single digit representing the number of digits in the fractional portion of the SECOND field. // '11:37:58.12345' n = 5; '11:37:58' n = 0 public const TYPE_TIME = 'TIME'; public const TYPE_TIMESTAMP = 'TIMESTAMP'; // TIMESTAMP [ ( n ) ] [ attributes [...] ] // '1999-01-01 23:59:59.1234' n = 4 // '1999-01-01 23:59:59' n = 0 public const TYPE_TIME_WITH_ZONE = 'TIME_WITH_ZONE'; // as TIME but // TIME [ ( n ) ] WITH ZONE [ attributes [...] ] // where insert value as a number from -12.59 to +14.00 23:59:59.1234 +02:00 public const TYPE_TIMESTAMP_WITH_ZONE = 'TIMESTAMP_WITH_ZONE'; // same as TYPE_TIME_WITH_ZONE /* character */ public const TYPE_CHAR = 'CHAR'; // [(n)] public const TYPE_CHARACTER = 'CHARACTER'; // = CHAR // { { CHARACTER | CHAR } [ ( n ) ] // [ { CHARACTER | CHAR } SET server_character_set ] | // GRAPHIC [ ( n ) ] // } [ attributes [...] ] // n = length, static // 64000 for LATIN charset, 32000 for UNICODE,GRAPHIC,KANJISJIS public const TYPE_VARCHAR = 'VARCHAR'; // { // { VARCHAR | { CHARACTER | CHAR } VARYING } ( n ) // [ { CHARACTER | CHAR } SET ] server_character_set | // LONG VARCHAR | // VARGRAPHIC ( n ) | // LONG VARGRAPHIC // } [ attributes [...] ] // n = length, variable // 64000 for LATIN charset, 32000 for UNICODE,GRAPHIC,KANJISJIS public const TYPE_CHARV = 'CHAR VARYING'; // = VARCHAR public const TYPE_CHARACTERV = 'CHARACTER VARYING'; // = VARCHAR public const TYPE_VARGRAPHIC = 'VARGRAPHIC'; // = VARCHAR // = VARCHAR but without n public const TYPE_LONG_VARCHAR = 'LONG VARCHAR'; // = VARCHAR with max n public const TYPE_LONG_VARGRAPHIC = 'LONG VARGRAPHIC'; // = LONG VARCHAR public const TYPE_CLOB = 'CLOB'; // { CHARACTER LARGE OBJECT | CLOB } // [ ( n [ K | M | G ] ) ] // [ { CHARACTER | CHAR } SET { LATIN | UNICODE } ] // [ attribute [...] ] // n - amount of // Bytes - no unit // K - K - max 2047937 for Latin, 1023968 for Unicode // M - M - max 1999 for Latin, 999 for Unicode // G - G - 1 and for LATIN only public const TYPE_CHARACTER_LARGE_OBJECT = 'CHARACTER LARGE OBJECT'; // = CLOB // Following types are listed due compatibility but they are treated as string /* Array */ // not implemented, because arrays are considered as user defined types /* Period */ // n represents fraction of seconds as in TIME / TIMESTAMP public const TYPE_PERIOD_DATE = 'PERIOD(DATE)'; // PERIOD(DATE) public const TYPE_PERIOD_TIME = 'PERIOD(TIME)'; // PERIOD(TIME [ ( n ) ] ) public const TYPE_PERIOD_TIMESTAMP = 'PERIOD TIMESTAMP'; // PERIOD(TIMESTAMP [ ( n ) ] ) public const TYPE_PERIOD_TIME_WITH_ZONE = 'PERIOD TIME WITH_ZONE'; // PERIOD(TIME [ ( n ) ] _WITH_ZONE ) // PERIOD(TIMESTAMP [ ( n ) ] _WITH_ZONE ) public const TYPE_PERIOD_TIMESTAMP_WITH_ZONE = 'PERIOD TIMESTAMP WITH_ZONE'; /* Intervals */ // n is always number of digits, m number of decimal digits for seconds. // INTERVAL HOUR(1) TO SECOND(2) = '9:59:59.99' public const TYPE_INTERVAL_SECOND = 'INTERVAL SECOND'; // INTERVAL SECOND [(n;[m])] public const TYPE_INTERVAL_MINUTE = 'INTERVAL MINUTE'; // INTERVAL MINUTE [(n)] public const TYPE_INTERVAL_MINUTE_TO_SECOND = 'INTERVAL MINUTE TO SECOND'; // INTERVAL MINUTE [(n)] TO SECOND [(m)] public const TYPE_INTERVAL_HOUR = 'INTERVAL HOUR'; // INTERVAL HOUR [(n)] public const TYPE_INTERVAL_HOUR_TO_SECOND = 'INTERVAL HOUR TO SECOND'; // INTERVAL HOUR [(n)] TO SECOND [(m)] public const TYPE_INTERVAL_HOUR_TO_MINUTE = 'INTERVAL HOUR TO MINUTE'; // INTERVAL HOUR [(n)] TO MINUTE public const TYPE_INTERVAL_DAY = 'INTERVAL DAY'; // INTERVAL DAY [(n)] public const TYPE_INTERVAL_DAY_TO_SECOND = 'INTERVAL DAY TO SECOND'; // INTERVAL DAY [(n)] TO SECOND [(m)] public const TYPE_INTERVAL_DAY_TO_MINUTE = 'INTERVAL DAY TO MINUTE'; // INTERVAL DAY [(n)] TO MINUTE public const TYPE_INTERVAL_DAY_TO_HOUR = 'INTERVAL DAY TO HOUR'; // INTERVAL DAY [(n)] TO HOUR public const TYPE_INTERVAL_MONTH = 'INTERVAL MONTH'; // INTERVAL MONTH public const TYPE_INTERVAL_YEAR = 'INTERVAL YEAR'; // INTERVAL YEAR [(n)] public const TYPE_INTERVAL_YEAR_TO_MONTH = 'INTERVAL YEAR TO MONTH'; // INTERVAL YEAR [(n)] TO MONTH // User Defined Types (UDP) are not supported // default lengths for different kinds of types. Used max values public const DEFAULT_BLOB_LENGTH = '1G'; public const DEFAULT_BYTE_LENGTH = 64000; public const DEFAULT_DATETIME_DIGIT_LENGTH = 4; public const DEFAULT_DECIMAL_LENGTH = '38,19'; public const DEFAULT_LATIN_CHAR_LENGTH = 64000; public const DEFAULT_LATIN_CLOB_LENGTH = '1999M'; public const DEFAULT_NON_LATIN_CHAR_LENGTH = 32000; public const DEFAULT_NON_LATIN_CLOB_LENGTH = '999M'; public const DEFAULT_SECOND_PRECISION_LENGTH = 6; public const DEFAULT_VALUE_TO_SECOND_PRECISION_LENGTH = '4,6'; // types where length isnt at the end of the type public const COMPLEX_LENGTH_DICT = [ self::TYPE_TIME_WITH_ZONE => 'TIME (%d) WITH TIME ZONE', self::TYPE_TIMESTAMP_WITH_ZONE => 'TIMESTAMP (%d) WITH TIME ZONE', self::TYPE_PERIOD_TIME => 'PERIOD(TIME (%d))', self::TYPE_PERIOD_TIMESTAMP => 'PERIOD(TIMESTAMP (%d))', self::TYPE_PERIOD_TIME_WITH_ZONE => 'PERIOD(TIME (%d) WITH TIME ZONE)', self::TYPE_PERIOD_TIMESTAMP_WITH_ZONE => 'PERIOD(TIMESTAMP (%d) WITH TIME ZONE)', self::TYPE_INTERVAL_DAY_TO_MINUTE => 'INTERVAL DAY (%d) TO MINUTE', self::TYPE_INTERVAL_DAY_TO_HOUR => 'INTERVAL DAY (%d) TO HOUR', self::TYPE_INTERVAL_HOUR_TO_MINUTE => 'INTERVAL HOUR (%d) TO MINUTE', self::TYPE_INTERVAL_MINUTE_TO_SECOND => 'INTERVAL MINUTE (%d) TO SECOND (%d)', self::TYPE_INTERVAL_HOUR_TO_SECOND => 'INTERVAL HOUR (%d) TO SECOND (%d)', self::TYPE_INTERVAL_DAY_TO_SECOND => 'INTERVAL DAY (%d) TO SECOND (%d)', self::TYPE_INTERVAL_YEAR_TO_MONTH => 'INTERVAL YEAR (%d) TO MONTH', ]; /** * Types without precision, scale, or length * This used to separate types when column is retrieved from database */ public const TYPES_WITHOUT_LENGTH = [ self::TYPE_BYTEINT, self::TYPE_BIGINT, self::TYPE_SMALLINT, self::TYPE_INTEGER, self::TYPE_INT, // self::TYPE_FLOAT, self::TYPE_DOUBLE_PRECISION, // self::TYPE_REAL, // self::TYPE_PERIOD_DATE, self::TYPE_LONG_VARCHAR, self::TYPE_LONG_VARGRAPHIC, ]; // syntax "TYPEXXX <length>" even if the length is not a single value, such as 38,38Similar blocks of code found in 2 locations. Consider refactoring. public const TYPES_WITH_SIMPLE_LENGTH = [ self::TYPE_BYTE, self::TYPE_VARBYTE, self::TYPE_TIME, self::TYPE_TIMESTAMP, self::TYPE_CHAR, self::TYPE_CHARACTER, // self::TYPE_VARCHAR, self::TYPE_CHARV, // self::TYPE_CHARACTERV, self::TYPE_VARGRAPHIC, self::TYPE_INTERVAL_MINUTE, self::TYPE_INTERVAL_HOUR, self::TYPE_INTERVAL_DAY, self::TYPE_INTERVAL_MONTH, self::TYPE_INTERVAL_YEAR, self::TYPE_DECIMAL, self::TYPE_NUMERIC, // alias self::TYPE_DEC, // self::TYPE_NUMBER, self::TYPE_BLOB, // ????? self::TYPE_BINARY_LARGE_OBJECT, // self::TYPE_CLOB, // ??? self::TYPE_CHARACTER_LARGE_OBJECT, // self::TYPE_INTERVAL_SECOND, ]; // types where CHARAET can be defined public const CHARACTER_SET_TYPES = [ self::TYPE_CHAR, self::TYPE_VARCHAR, self::TYPE_CLOB, self::TYPE_CHAR, self::TYPE_CHARV, self::TYPE_CHARACTERV, self::TYPE_VARGRAPHIC, self::TYPE_LONG_VARCHAR, self::TYPE_LONG_VARGRAPHIC, self::TYPE_CHARACTER_LARGE_OBJECT, ]; //https://docs.teradata.com/r/rgAb27O_xRmMVc_aQq2VGw/6CYL2QcAvXykzEc8mG__Xg public const CODE_TO_TYPE = [ 'I8' => self::TYPE_BIGINT, 'BO' => self::TYPE_BLOB, 'BF' => self::TYPE_BYTE, 'BV' => self::TYPE_VARBYTE, 'I1' => self::TYPE_BYTEINT, 'CF' => self::TYPE_CHAR, 'CV' => self::TYPE_VARCHAR, 'CO' => self::TYPE_CLOB, 'D' => self::TYPE_DECIMAL, 'DA' => self::TYPE_DATE, 'F' => self::TYPE_FLOAT, 'I' => self::TYPE_INTEGER, 'DY' => self::TYPE_INTERVAL_DAY, 'DH' => self::TYPE_INTERVAL_DAY_TO_HOUR, 'DM' => self::TYPE_INTERVAL_DAY_TO_MINUTE, 'DS' => self::TYPE_INTERVAL_DAY_TO_SECOND, 'HR' => self::TYPE_INTERVAL_HOUR, 'HM' => self::TYPE_INTERVAL_HOUR_TO_MINUTE, 'HS' => self::TYPE_INTERVAL_HOUR_TO_SECOND, 'MI' => self::TYPE_INTERVAL_MINUTE, 'MS' => self::TYPE_INTERVAL_MINUTE_TO_SECOND, 'MO' => self::TYPE_INTERVAL_MONTH, 'SC' => self::TYPE_INTERVAL_SECOND, 'YR' => self::TYPE_INTERVAL_YEAR, 'YM' => self::TYPE_INTERVAL_YEAR_TO_MONTH, 'N' => self::TYPE_NUMBER, 'PD' => self::TYPE_PERIOD_DATE, 'PT' => self::TYPE_PERIOD_TIME, 'PZ' => self::TYPE_PERIOD_TIME_WITH_ZONE, 'PS' => self::TYPE_PERIOD_TIMESTAMP, 'PM' => self::TYPE_PERIOD_TIMESTAMP_WITH_ZONE, 'I2' => self::TYPE_SMALLINT, 'AT' => self::TYPE_TIME, 'TS' => self::TYPE_TIMESTAMP, 'TZ' => self::TYPE_TIME_WITH_ZONE, 'SZ' => self::TYPE_TIMESTAMP_WITH_ZONE, ]; public const TYPES = [ self::TYPE_BIGINT, self::TYPE_BLOB, self::TYPE_BYTE, self::TYPE_VARBYTE, self::TYPE_BYTEINT, self::TYPE_CHARACTER, self::TYPE_VARCHAR, self::TYPE_CLOB, self::TYPE_DECIMAL, self::TYPE_DATE, self::TYPE_FLOAT, self::TYPE_INTEGER, self::TYPE_INTERVAL_DAY, self::TYPE_INTERVAL_DAY_TO_HOUR, self::TYPE_INTERVAL_DAY_TO_MINUTE, self::TYPE_INTERVAL_DAY_TO_SECOND, self::TYPE_INTERVAL_HOUR, self::TYPE_INTERVAL_HOUR_TO_MINUTE, self::TYPE_INTERVAL_HOUR_TO_SECOND, self::TYPE_INTERVAL_MINUTE, self::TYPE_INTERVAL_MINUTE_TO_SECOND, self::TYPE_INTERVAL_MONTH, self::TYPE_INTERVAL_SECOND, self::TYPE_INTERVAL_YEAR, self::TYPE_INTERVAL_YEAR_TO_MONTH, self::TYPE_NUMBER, self::TYPE_PERIOD_DATE, self::TYPE_PERIOD_TIME, self::TYPE_PERIOD_TIME_WITH_ZONE, self::TYPE_PERIOD_TIMESTAMP, self::TYPE_PERIOD_TIMESTAMP_WITH_ZONE, self::TYPE_SMALLINT, self::TYPE_TIME, self::TYPE_TIMESTAMP, self::TYPE_TIME_WITH_ZONE, self::TYPE_TIMESTAMP_WITH_ZONE, // aliases self::TYPE_INT, self::TYPE_CHAR, self::TYPE_CHARV, self::TYPE_CHARACTERV, self::TYPE_VARGRAPHIC, self::TYPE_LONG_VARCHAR, self::TYPE_LONG_VARGRAPHIC, self::TYPE_CHARACTER_LARGE_OBJECT, self::TYPE_BINARY_LARGE_OBJECT, self::TYPE_NUMERIC, self::TYPE_DEC, self::TYPE_FLOAT, self::TYPE_DOUBLE_PRECISION, self::TYPE_REAL, ]; // these types expect invalid default length given TD. e.g. NUMBER returns -128,-128. -> has to be redefined public const TYPES_WITH_INVALID_DEFAULT_LENGTH = [ self::TYPE_NUMBER => '-128,-128', ]; private bool $isLatin = false; // depends on Char Type column in HELP TABLE column // 1 latin, 2 unicode, 3 kanjiSJIS, 4 graphic, 5 graphic, 0 others /** * @param array{length?:string|null, nullable?:bool, default?:string|null, isLatin?:bool} $options * @throws InvalidLengthException * @throws InvalidOptionException * @throws InvalidTypeException */ public function __construct(string $type, array $options = []) { if (isset($options['isLatin'])) { $this->isLatin = (boolean) $options['isLatin']; } $this->validateType($type); $options['length'] = $this->consolidateLength($type, $options['length'] ?? null); $this->validateLength($type, $options['length'] ?? null); $diff = array_diff(array_keys($options), ['length', 'nullable', 'default', 'isLatin']); if ($diff !== []) { throw new InvalidOptionException("Option '{$diff[0]}' not supported"); } parent::__construct($type, $options); } private function consolidateLength(string $type, ?string $length = null): ?string { if ($length !== null && array_key_exists($type, self::TYPES_WITH_INVALID_DEFAULT_LENGTH) && $length === self::TYPES_WITH_INVALID_DEFAULT_LENGTH[$type] ) { return null; } return $length; } /** * @throws \Exception */ public static function convertCodeToType(string $code): string { if (!array_key_exists($code, self::CODE_TO_TYPE)) { throw new Exception("Type code {$code} is not supported"); } return self::CODE_TO_TYPE[$code]; } public function getSQLDefinition(): string { $definition = $this->buildTypeWithLength(); if (!$this->isNullable()) { $definition .= ' NOT NULL'; } if ($this->getDefault() !== null) { $definition .= ' DEFAULT ' . $this->getDefault(); } if (in_array($this->getType(), self::CHARACTER_SET_TYPES, true)) { $definition .= ' CHARACTER SET ' . ($this->isLatin() ? 'LATIN' : 'UNICODE'); } return $definition; } /** * generates type with length * most of the types just append it, but some of them are complex and some have no length... * used here and in i/e lib */Function `buildTypeWithLength` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring. public function buildTypeWithLength(): string { $type = $this->getType(); $definition = $type; if (!in_array($definition, self::TYPES_WITHOUT_LENGTH)) { $length = $this->getLength(); $length ??= $this->getDefaultLength(); // length is set, use it if ($length !== null && $length !== '') { if (in_array($definition, self::TYPES_WITH_SIMPLE_LENGTH)) { $definition .= sprintf(' (%s)', $length); } elseif (array_key_exists($definition, self::COMPLEX_LENGTH_DICT)) { $definition = $this->buildComplexLength($type, $length); } } } return $definition; } /** * builds SQL definition for types which don't just append the length behind the type name * * @param string|int|null $lengthString */ //phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint private function buildComplexLength(string $type, $lengthString): string { $parts = explode(',', (string) $lengthString); return sprintf(self::COMPLEX_LENGTH_DICT[$type], ...$parts); } private function isLatin(): bool { return $this->isLatin; } /** * Unlike RS or SNFLK which sets default values for types to max * Synapse sets default length to min, so when length is empty we need to set maximum values * to maintain same behavior as with RS and SNFLK * * @return int|string|null */ //phpcs:ignore SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHintMethod `getDefaultLength` has 57 lines of code (exceeds 25 allowed). Consider refactoring.
Function `getDefaultLength` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.
The method getDefaultLength() has a Cyclomatic Complexity of 40. The configured cyclomatic complexity threshold is 10. private function getDefaultLength() { $out = null; switch ($this->type) { // decimals case self::TYPE_DECIMAL: case self::TYPE_NUMERIC: case self::TYPE_DEC: // number case self::TYPE_NUMBER: $out = self::DEFAULT_DECIMAL_LENGTH; break; case self::TYPE_BLOB: case self::TYPE_BINARY_LARGE_OBJECT: $out = self::DEFAULT_BLOB_LENGTH; break; case self::TYPE_CLOB: case self::TYPE_CHARACTER_LARGE_OBJECT: $out = $this->isLatin() ? self::DEFAULT_LATIN_CLOB_LENGTH : self::DEFAULT_NON_LATIN_CLOB_LENGTH; break; case self::TYPE_TIME_WITH_ZONE: case self::TYPE_TIMESTAMP_WITH_ZONE: case self::TYPE_TIMESTAMP: case self::TYPE_TIME: case self::TYPE_PERIOD_TIME: case self::TYPE_PERIOD_TIME_WITH_ZONE: case self::TYPE_PERIOD_TIMESTAMP: case self::TYPE_PERIOD_TIMESTAMP_WITH_ZONE: $out = self::DEFAULT_SECOND_PRECISION_LENGTH; break; case self::TYPE_INTERVAL_DAY_TO_SECOND: case self::TYPE_INTERVAL_MINUTE_TO_SECOND: case self::TYPE_INTERVAL_HOUR_TO_SECOND: case self::TYPE_INTERVAL_SECOND: $out = self::DEFAULT_VALUE_TO_SECOND_PRECISION_LENGTH; break; case self::TYPE_INTERVAL_DAY_TO_MINUTE: case self::TYPE_INTERVAL_DAY_TO_HOUR: case self::TYPE_INTERVAL_HOUR_TO_MINUTE: case self::TYPE_INTERVAL_YEAR_TO_MONTH: case self::TYPE_INTERVAL_MINUTE: case self::TYPE_INTERVAL_HOUR: case self::TYPE_INTERVAL_DAY: case self::TYPE_INTERVAL_MONTH: case self::TYPE_INTERVAL_YEAR: $out = self::DEFAULT_DATETIME_DIGIT_LENGTH; break; case self::TYPE_BYTE: case self::TYPE_VARBYTE: $out = self::DEFAULT_BYTE_LENGTH; break; case self::TYPE_CHAR: case self::TYPE_CHARACTER: case self::TYPE_VARCHAR: case self::TYPE_CHARV: case self::TYPE_CHARACTERV: case self::TYPE_VARGRAPHIC: $out = $this->isLatin() ? self::DEFAULT_LATIN_CHAR_LENGTH : self::DEFAULT_NON_LATIN_CHAR_LENGTH; break; } return $out; } /** * @return array{type:string,length:string|null,nullable:bool} */ public function toArray(): array { return [ 'type' => $this->getType(), 'length' => $this->getLength(), 'nullable' => $this->isNullable(), ]; } /** * @throws InvalidTypeException */ private function validateType(string $type): void { if (!in_array(strtoupper($type), $this::TYPES, true)) { throw new InvalidTypeException(sprintf('"%s" is not a valid type', $type)); } } /** * @param null|int|string $length * @throws InvalidLengthException */ //phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHintMethod `validateLength` has 76 lines of code (exceeds 25 allowed). Consider refactoring.
Function `validateLength` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.
The method validateLength() has a Cyclomatic Complexity of 44. The configured cyclomatic complexity threshold is 10. private function validateLength(string $type, $length = null): void { $valid = true; switch (strtoupper($type)) { case self::TYPE_DECIMAL: case self::TYPE_NUMERIC: case self::TYPE_DEC: case self::TYPE_NUMBER: $valid = $this->validateNumericLength($length, 38, 38); break; case self::TYPE_INTERVAL_SECOND: case self::TYPE_INTERVAL_MINUTE_TO_SECOND: case self::TYPE_INTERVAL_HOUR_TO_SECOND: case self::TYPE_INTERVAL_DAY_TO_SECOND: $valid = $this->validateNumericLength($length, 4, 6, false); break; case self::TYPE_TIME: case self::TYPE_TIMESTAMP: case self::TYPE_TIME_WITH_ZONE: case self::TYPE_TIMESTAMP_WITH_ZONE: case self::TYPE_PERIOD_TIME: case self::TYPE_PERIOD_TIME_WITH_ZONE: case self::TYPE_PERIOD_TIMESTAMP: case self::TYPE_PERIOD_TIMESTAMP_WITH_ZONE: $valid = $this->validateMaxLength($length, 6, 0); break; case self::TYPE_INTERVAL_MINUTE: case self::TYPE_INTERVAL_HOUR: case self::TYPE_INTERVAL_DAY: case self::TYPE_INTERVAL_MONTH: case self::TYPE_INTERVAL_YEAR: case self::TYPE_INTERVAL_DAY_TO_MINUTE: case self::TYPE_INTERVAL_HOUR_TO_MINUTE: case self::TYPE_INTERVAL_DAY_TO_HOUR: case self::TYPE_INTERVAL_YEAR_TO_MONTH: $valid = $this->validateMaxLength($length, 4); break; case self::TYPE_BYTE: case self::TYPE_VARBYTE: $valid = $this->validateMaxLength($length, 64000); break; case self::TYPE_CHAR: case self::TYPE_CHARACTER: case self::TYPE_VARCHAR: case self::TYPE_CHARV: case self::TYPE_CHARACTERV: case self::TYPE_VARGRAPHIC: $valid = $this->validateMaxLength($length, $this->isLatin() ? 64000 : 32000); break; case self::TYPE_CLOB: case self::TYPE_CHARACTER_LARGE_OBJECT: $isLatin = $this->isLatin(); $valid = $this->validateLOBLength( $length, [ 'noUnit' => $isLatin ? 2_097_088_000 : 1_048_544_000, 'K' => $isLatin ? 2_047_937 : 1_023_968, 'M' => $isLatin ? 1999 : 999, 'G' => $isLatin ? 1 : 0, ] ); break; case self::TYPE_BLOB: case self::TYPE_BINARY_LARGE_OBJECT: $valid = $this->validateLOBLength( $length, [ 'noUnit' => 2_097_088_000, 'K' => 2_047_937, 'M' => 1999, 'G' => 1, ] ); break; } if (!$valid) { throw new InvalidLengthException("'{$length}' is not valid length for {$type}"); } } /** * @param array<string, int> $maxTab table (array) with max values * @param null|int|string $length */ //phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint private function validateLOBLength($length, array $maxTab): bool { if ($this->isEmpty($length)) { return true; } if (!preg_match('/^([1-9]\d*)\s*(M|K|G)?$/', (string) $length, $out)) { return false; } if (count($out) === 2) { // no unit return $out[1] < $maxTab['noUnit'] && $out[1] >= 1; } if (count($out) === 3) { // with unit return $out[1] <= $maxTab[$out[2]] && $out[1] >= 1; }Avoid too many `return` statements within this method. return false; } Method `getBasetype` has 33 lines of code (exceeds 25 allowed). Consider refactoring.
Function `getBasetype` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
The method getBasetype() has a Cyclomatic Complexity of 18. The configured cyclomatic complexity threshold is 10. public function getBasetype(): string { switch (strtoupper($this->type)) { case self::TYPE_BYTEINT: case self::TYPE_INTEGER: case self::TYPE_INT: case self::TYPE_BIGINT: case self::TYPE_SMALLINT: $basetype = BaseType::INTEGER; break; case self::TYPE_DECIMAL: case self::TYPE_DEC: case self::TYPE_NUMERIC: case self::TYPE_NUMBER: $basetype = BaseType::NUMERIC; break; case self::TYPE_FLOAT: case self::TYPE_DOUBLE_PRECISION: case self::TYPE_REAL: $basetype = BaseType::FLOAT; break; case self::TYPE_DATE: $basetype = BaseType::DATE; break; case self::TYPE_TIME: case self::TYPE_TIME_WITH_ZONE: case self::TYPE_TIMESTAMP: case self::TYPE_TIMESTAMP_WITH_ZONE: $basetype = BaseType::TIMESTAMP; break; default: $basetype = BaseType::STRING; break; } return $basetype; } Avoid unused parameters such as '$basetype'. public static function getTypeByBasetype(string $basetype): string { throw new LogicException('Method is not implemented yet.'); }}