@@ -62,7 +62,7 @@ public function assertCanRepresent(int $sourceVariableCount): void
6262
6363 /**
6464 * @param list<array<string, mixed>> $variables
65- * @param list<list<int|float|string|null >> $rows
65+ * @param list<array<mixed >> $rows Untrusted cells; this is the type gate.
6666 */
6767 public function assertDataset (array $ variables , array $ rows , ?PDO $ pdo = null ): void
6868 {
@@ -93,37 +93,38 @@ public function assertDataset(array $variables, array $rows, ?PDO $pdo = null):
9393 throw new UnsupportedOperation (DiagnosticCode::InvalidSourceDataset, 'Every source case must contain exactly one value per source variable. ' );
9494 }
9595 $ encodedRowBytes = 0 ;
96+ // Branch on the value type first: a numeric cell costs two type
97+ // tests and one finiteness test. Rules, order and messages match
98+ // the previous per-cell checks for list rows.
9699 foreach ($ row as $ index => $ value ) {
97100 $ kind = $ storageKinds [$ index ];
98- if ($ kind === 'string ' && !is_string ($ value )) {
99- throw new UnsupportedOperation (
100- DiagnosticCode::InvalidSourceDataset,
101- 'SPSS string values must be non-null strings. ' ,
102- );
101+ if (is_string ($ value )) {
102+ if ($ kind === 'numeric ' ) {
103+ $ this ->invalidNumericValue ();
104+ }
105+ if (strlen ($ value ) > $ maximumValueBytes ) {
106+ $ this ->capabilityExceeded ('encoded string value ' , strlen ($ value ), $ maximumValueBytes );
107+ }
108+ $ encodedRowBytes += strlen ($ value );
109+ continue ;
103110 }
104- if ($ kind === 'numeric '
105- && $ value !== null
106- && !is_int ($ value )
107- && !is_float ($ value )
108- ) {
111+ if ($ kind === 'string ' ) {
109112 throw new UnsupportedOperation (
110113 DiagnosticCode::InvalidSourceDataset,
111- 'SPSS numeric values must be binary64 numbers or system-missing NULL. ' ,
112- );
113- }
114- if ($ kind === 'numeric '
115- && (is_int ($ value ) || is_float ($ value ))
116- && !is_finite ((float ) $ value )
117- ) {
118- throw new UnsupportedOperation (
119- DiagnosticCode::TargetCapabilityExceeded,
120- $ this ->driverName () . ' rejects non-finite SPSS numeric values before mutation. ' ,
114+ 'SPSS string values must be non-null strings. ' ,
121115 );
122116 }
123- if (is_string ($ value ) && strlen ($ value ) > $ maximumValueBytes ) {
124- $ this ->capabilityExceeded ('encoded string value ' , strlen ($ value ), $ maximumValueBytes );
117+ if (is_float ($ value )) {
118+ if (!is_finite ($ value )) {
119+ throw new UnsupportedOperation (
120+ DiagnosticCode::TargetCapabilityExceeded,
121+ $ this ->driverName () . ' rejects non-finite SPSS numeric values before mutation. ' ,
122+ );
123+ }
124+ } elseif ($ value !== null && !is_int ($ value )) {
125+ $ this ->invalidNumericValue ();
125126 }
126- $ encodedRowBytes += is_string ( $ value ) ? strlen ( $ value ) : 8 ;
127+ $ encodedRowBytes += 8 ;
127128 }
128129 if ($ encodedRowBytes > $ maximumEncodedCaseBytes ) {
129130 $ this ->capabilityExceeded ('encoded case payload ' , $ encodedRowBytes , $ maximumEncodedCaseBytes );
@@ -167,6 +168,14 @@ protected function rowStorageBytes(string $kind, int $declaredWidth): int
167168 return $ kind === 'string ' ? $ declaredWidth : 8 ;
168169 }
169170
171+ private function invalidNumericValue (): never
172+ {
173+ throw new UnsupportedOperation (
174+ DiagnosticCode::InvalidSourceDataset,
175+ 'SPSS numeric values must be binary64 numbers or system-missing NULL. ' ,
176+ );
177+ }
178+
170179 private function capabilityExceeded (string $ limit , int $ actual , int $ maximum ): never
171180 {
172181 throw new UnsupportedOperation (
0 commit comments