MCPcopy Create free account
hub / github.com/erans/pgsqlite / encode_array

Method encode_array

src/protocol/binary.rs:274–418  ·  view source on GitHub ↗

Encode an array value PostgreSQL array binary format: - ndim (i32): number of dimensions - dataoffset (i32): offset to data, 0 if no NULLs - elemtype (i32): element type OID - For each dimension: - dim_size (i32): number of elements in this dimension - lower_bound (i32): lower bound (typically 1) - NULL bitmap (optional): bit array indicating NULL positions - Elements: each prefixed with length (i

(
        array_str: &str,
        elem_type_oid: i32,
    )

Source from the content-addressed store, hash-verified

272 /// - NULL bitmap (optional): bit array indicating NULL positions
273 /// - Elements: each prefixed with length (i32), -1 for NULL
274 pub fn encode_array(
275 array_str: &str,
276 elem_type_oid: i32,
277 ) -> Result<Vec<u8>, PgSqliteError> {
278 // Input validation
279 if array_str.len() > MAX_STRING_LENGTH {
280 return Err(PgSqliteError::InvalidParameter(
281 format!("Array string too long: {} bytes (max: {})", array_str.len(), MAX_STRING_LENGTH)
282 ));
283 }
284
285 debug!("encode_array called with: '{}', type_oid: {}", array_str, elem_type_oid);
286
287 // Convert PostgreSQL format to JSON if needed
288 let json_str = Self::pg_array_to_json(array_str)
289 .map_err(|e| PgSqliteError::Protocol(format!("Array format conversion failed: {}", e)))?;
290 debug!("After conversion to JSON: '{}'", json_str);
291
292 // Additional JSON validation
293 Self::validate_json_security(&json_str)?;
294
295 // Parse JSON array
296 let array: serde_json::Value = serde_json::from_str(&json_str)
297 .map_err(|e| PgSqliteError::InvalidParameter(format!("Invalid JSON array: {e}")))?;
298
299 let elements = array.as_array()
300 .ok_or_else(|| PgSqliteError::InvalidParameter("Not a JSON array".to_string()))?;
301
302 // Array size validation
303 if elements.len() > MAX_ARRAY_SIZE {
304 return Err(PgSqliteError::InvalidParameter(
305 format!("Array too large: {} elements (max: {})", elements.len(), MAX_ARRAY_SIZE)
306 ));
307 }
308
309 if elements.is_empty() {
310 // Empty array
311 let mut result = Vec::new();
312 result.extend_from_slice(&0i32.to_be_bytes()); // ndim = 0
313 result.extend_from_slice(&0i32.to_be_bytes()); // dataoffset = 0
314 result.extend_from_slice(&elem_type_oid.to_be_bytes()); // elemtype
315 return Ok(result);
316 }
317
318 // Check for NULLs
319 let has_nulls = elements.iter().any(|e| e.is_null());
320 debug!("Array has {} elements, has_nulls: {}", elements.len(), has_nulls);
321
322 let mut result = Vec::new();
323
324 // Header
325 result.extend_from_slice(&1i32.to_be_bytes()); // ndim = 1 (1D array)
326
327 // flags field: 1 if array has nulls, 0 otherwise (PostgreSQL binary protocol format)
328 // Note: This is NOT dataoffset! The binary protocol uses a simple flag.
329 result.extend_from_slice(&(if has_nulls { 1i32 } else { 0i32 }).to_be_bytes());
330 result.extend_from_slice(&elem_type_oid.to_be_bytes()); // elemtype
331

Callers

nothing calls this directly

Calls 3

to_oidMethod · 0.80
lenMethod · 0.45
is_emptyMethod · 0.45

Tested by

no test coverage detected