Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
229
vendor/ruvector/crates/ruvector-postgres/install/config/ruvector.conf.template
vendored
Normal file
229
vendor/ruvector/crates/ruvector-postgres/install/config/ruvector.conf.template
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
# =============================================================================
|
||||
# RuVector PostgreSQL Extension Configuration
|
||||
# =============================================================================
|
||||
#
|
||||
# This file contains configuration options for the RuVector extension.
|
||||
# Copy this file to your PostgreSQL data directory and include it in
|
||||
# postgresql.conf with: include = 'ruvector.conf'
|
||||
#
|
||||
# Or set individual parameters with: ALTER SYSTEM SET ruvector.param = value;
|
||||
#
|
||||
|
||||
# =============================================================================
|
||||
# SIMD Configuration
|
||||
# =============================================================================
|
||||
|
||||
# SIMD instruction set to use for distance calculations
|
||||
# Options:
|
||||
# - 'auto' : Auto-detect best available (recommended)
|
||||
# - 'avx512' : Force AVX-512 (16 floats per operation)
|
||||
# - 'avx2' : Force AVX2 (8 floats per operation)
|
||||
# - 'neon' : Force ARM NEON (4 floats per operation)
|
||||
# - 'scalar' : Disable SIMD (portable, slowest)
|
||||
# Default: 'auto'
|
||||
#ruvector.simd_mode = 'auto'
|
||||
|
||||
# Enable SIMD prefetching for better cache utilization
|
||||
# This can improve performance for large vector operations
|
||||
# Default: on
|
||||
#ruvector.simd_prefetch = on
|
||||
|
||||
# =============================================================================
|
||||
# Memory Configuration
|
||||
# =============================================================================
|
||||
|
||||
# Maximum memory allocation for vector operations (in MB)
|
||||
# Set to 0 for unlimited (uses PostgreSQL's work_mem)
|
||||
# Default: 0 (use work_mem)
|
||||
#ruvector.max_memory_mb = 0
|
||||
|
||||
# Enable memory pooling for frequently accessed vectors
|
||||
# Reduces allocation overhead for repeated operations
|
||||
# Default: on
|
||||
#ruvector.memory_pool_enabled = on
|
||||
|
||||
# Memory pool size (in MB)
|
||||
# Only used when memory_pool_enabled = on
|
||||
# Default: 64
|
||||
#ruvector.memory_pool_size_mb = 64
|
||||
|
||||
# Enable zero-copy operations where possible
|
||||
# Reduces memory copies but may hold references longer
|
||||
# Default: on
|
||||
#ruvector.zero_copy = on
|
||||
|
||||
# =============================================================================
|
||||
# Distance Calculation Configuration
|
||||
# =============================================================================
|
||||
|
||||
# Default distance metric for operators
|
||||
# Options: 'l2' (Euclidean), 'cosine', 'ip' (inner product)
|
||||
# Default: 'l2'
|
||||
#ruvector.default_distance_metric = 'l2'
|
||||
|
||||
# Enable parallel distance computation for batch operations
|
||||
# Uses multiple CPU cores for large vector comparisons
|
||||
# Default: on
|
||||
#ruvector.parallel_distance = on
|
||||
|
||||
# Minimum number of vectors to enable parallel processing
|
||||
# Below this threshold, sequential processing is used
|
||||
# Default: 1000
|
||||
#ruvector.parallel_threshold = 1000
|
||||
|
||||
# Number of worker threads for parallel operations
|
||||
# Set to 0 to use PostgreSQL's max_parallel_workers
|
||||
# Default: 0
|
||||
#ruvector.parallel_workers = 0
|
||||
|
||||
# =============================================================================
|
||||
# Index Configuration (HNSW)
|
||||
# =============================================================================
|
||||
|
||||
# Default ef_construction for HNSW index building
|
||||
# Higher values = better quality, slower build
|
||||
# Range: 4-1000, Default: 64
|
||||
#ruvector.hnsw_ef_construction = 64
|
||||
|
||||
# Default M parameter for HNSW index
|
||||
# Number of bi-directional links per node
|
||||
# Higher values = better quality, more memory
|
||||
# Range: 2-100, Default: 16
|
||||
#ruvector.hnsw_m = 16
|
||||
|
||||
# Default ef_search for HNSW queries
|
||||
# Higher values = better recall, slower queries
|
||||
# Range: 1-1000, Default: 40
|
||||
#ruvector.hnsw_ef_search = 40
|
||||
|
||||
# =============================================================================
|
||||
# Index Configuration (IVF-Flat)
|
||||
# =============================================================================
|
||||
|
||||
# Default number of lists (clusters) for IVF-Flat index
|
||||
# More lists = faster search, longer build
|
||||
# Recommendation: sqrt(num_vectors) to 4*sqrt(num_vectors)
|
||||
# Default: 100
|
||||
#ruvector.ivfflat_lists = 100
|
||||
|
||||
# Default number of probes for IVF-Flat queries
|
||||
# More probes = better recall, slower queries
|
||||
# Range: 1-lists, Default: 10
|
||||
#ruvector.ivfflat_probes = 10
|
||||
|
||||
# =============================================================================
|
||||
# Quantization Configuration
|
||||
# =============================================================================
|
||||
|
||||
# Enable product quantization for memory compression
|
||||
# Reduces memory usage by 4-32x with some accuracy loss
|
||||
# Default: off
|
||||
#ruvector.quantization_enabled = off
|
||||
|
||||
# Number of subquantizers for product quantization
|
||||
# More subquantizers = better accuracy, more memory
|
||||
# Must divide vector dimensions evenly
|
||||
# Default: 8
|
||||
#ruvector.pq_m = 8
|
||||
|
||||
# Bits per subquantizer (determines codebook size)
|
||||
# Options: 4, 8, 16 (256, 65536, 4B centroids)
|
||||
# Default: 8
|
||||
#ruvector.pq_bits = 8
|
||||
|
||||
# Enable scalar quantization (int8) for faster operations
|
||||
# Reduces memory by 4x with minimal accuracy loss
|
||||
# Default: off
|
||||
#ruvector.scalar_quantization = off
|
||||
|
||||
# =============================================================================
|
||||
# Temporal Functions Configuration
|
||||
# =============================================================================
|
||||
|
||||
# Default alpha for exponential moving average
|
||||
# Range: 0.0-1.0, Default: 0.1
|
||||
#ruvector.temporal_ema_alpha = 0.1
|
||||
|
||||
# Enable temporal compression (delta encoding)
|
||||
# Default: off
|
||||
#ruvector.temporal_compression = off
|
||||
|
||||
# =============================================================================
|
||||
# Attention Functions Configuration
|
||||
# =============================================================================
|
||||
|
||||
# Default scaling mode for attention scores
|
||||
# Options: 'sqrt_dim', 'none', 'learned'
|
||||
# Default: 'sqrt_dim'
|
||||
#ruvector.attention_scale_mode = 'sqrt_dim'
|
||||
|
||||
# Maximum number of attention heads
|
||||
# Default: 16
|
||||
#ruvector.attention_max_heads = 16
|
||||
|
||||
# =============================================================================
|
||||
# Graph Functions Configuration
|
||||
# =============================================================================
|
||||
|
||||
# Default damping factor for PageRank calculations
|
||||
# Range: 0.0-1.0, Default: 0.85
|
||||
#ruvector.graph_damping = 0.85
|
||||
|
||||
# Default similarity threshold for graph connectivity
|
||||
# Range: 0.0-1.0, Default: 0.5
|
||||
#ruvector.graph_similarity_threshold = 0.5
|
||||
|
||||
# =============================================================================
|
||||
# Logging Configuration
|
||||
# =============================================================================
|
||||
|
||||
# Log level for RuVector messages
|
||||
# Options: 'debug', 'info', 'warning', 'error'
|
||||
# Default: 'info'
|
||||
#ruvector.log_level = 'info'
|
||||
|
||||
# Log SIMD instruction usage (for debugging/optimization)
|
||||
# Default: off
|
||||
#ruvector.log_simd_ops = off
|
||||
|
||||
# Log distance calculation statistics
|
||||
# Default: off
|
||||
#ruvector.log_distance_stats = off
|
||||
|
||||
# Log memory allocation patterns
|
||||
# Default: off
|
||||
#ruvector.log_memory_stats = off
|
||||
|
||||
# =============================================================================
|
||||
# Performance Tuning Presets
|
||||
# =============================================================================
|
||||
#
|
||||
# Preset: High Throughput (many small queries)
|
||||
# -------------------------------------------------
|
||||
# ruvector.parallel_distance = off
|
||||
# ruvector.memory_pool_enabled = on
|
||||
# ruvector.zero_copy = on
|
||||
# ruvector.hnsw_ef_search = 20
|
||||
#
|
||||
# Preset: High Accuracy (fewer queries, best recall)
|
||||
# -------------------------------------------------
|
||||
# ruvector.parallel_distance = on
|
||||
# ruvector.hnsw_ef_search = 100
|
||||
# ruvector.ivfflat_probes = 50
|
||||
# ruvector.quantization_enabled = off
|
||||
#
|
||||
# Preset: Low Memory (large datasets)
|
||||
# -------------------------------------------------
|
||||
# ruvector.quantization_enabled = on
|
||||
# ruvector.pq_m = 16
|
||||
# ruvector.pq_bits = 8
|
||||
# ruvector.scalar_quantization = on
|
||||
# ruvector.memory_pool_size_mb = 32
|
||||
#
|
||||
# Preset: Real-time (minimal latency)
|
||||
# -------------------------------------------------
|
||||
# ruvector.parallel_distance = off
|
||||
# ruvector.memory_pool_enabled = on
|
||||
# ruvector.hnsw_ef_search = 10
|
||||
# ruvector.ivfflat_probes = 1
|
||||
#
|
||||
753
vendor/ruvector/crates/ruvector-postgres/install/install.sh
vendored
Executable file
753
vendor/ruvector/crates/ruvector-postgres/install/install.sh
vendored
Executable file
@@ -0,0 +1,753 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# RuVector PostgreSQL Extension Installer
|
||||
# High-performance vector similarity search with SIMD optimization
|
||||
#
|
||||
# Usage: ./install.sh [OPTIONS]
|
||||
#
|
||||
# Options:
|
||||
# --pg-version VERSION PostgreSQL version (14, 15, 16, 17)
|
||||
# --pg-config PATH Path to pg_config binary
|
||||
# --build-from-source Build from source (default: use pre-built if available)
|
||||
# --simd MODE SIMD mode: auto, avx512, avx2, neon, scalar (default: auto)
|
||||
# --prefix PATH Installation prefix (default: auto-detect)
|
||||
# --config FILE Configuration file path
|
||||
# --skip-tests Skip installation tests
|
||||
# --uninstall Uninstall RuVector
|
||||
# --upgrade Upgrade existing installation
|
||||
# --dry-run Show what would be done without making changes
|
||||
# --verbose Verbose output
|
||||
# --help Show this help message
|
||||
#
|
||||
set -e
|
||||
|
||||
# ============================================================================
|
||||
# Configuration
|
||||
# ============================================================================
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
RUVECTOR_VERSION="0.1.0"
|
||||
EXTENSION_NAME="ruvector"
|
||||
|
||||
# Default options
|
||||
PG_VERSION=""
|
||||
PG_CONFIG=""
|
||||
BUILD_FROM_SOURCE=false
|
||||
SIMD_MODE="auto"
|
||||
INSTALL_PREFIX=""
|
||||
CONFIG_FILE=""
|
||||
SKIP_TESTS=false
|
||||
UNINSTALL=false
|
||||
UPGRADE=false
|
||||
DRY_RUN=false
|
||||
VERBOSE=false
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ============================================================================
|
||||
# Helper Functions
|
||||
# ============================================================================
|
||||
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1" >&2
|
||||
}
|
||||
|
||||
log_verbose() {
|
||||
if [ "$VERBOSE" = true ]; then
|
||||
echo -e "${CYAN}[DEBUG]${NC} $1"
|
||||
fi
|
||||
}
|
||||
|
||||
die() {
|
||||
log_error "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
run_cmd() {
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_info "[DRY-RUN] Would run: $*"
|
||||
return 0
|
||||
fi
|
||||
if [ "$VERBOSE" = true ]; then
|
||||
log_verbose "Running: $*"
|
||||
"$@"
|
||||
else
|
||||
"$@" >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
check_command() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Environment Detection
|
||||
# ============================================================================
|
||||
|
||||
detect_os() {
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS_NAME="$ID"
|
||||
OS_VERSION="$VERSION_ID"
|
||||
OS_PRETTY="$PRETTY_NAME"
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
OS_NAME="rhel"
|
||||
OS_VERSION=$(cat /etc/redhat-release | grep -oP '\d+' | head -1)
|
||||
OS_PRETTY=$(cat /etc/redhat-release)
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
OS_NAME="macos"
|
||||
OS_VERSION=$(sw_vers -productVersion)
|
||||
OS_PRETTY="macOS $OS_VERSION"
|
||||
else
|
||||
OS_NAME="unknown"
|
||||
OS_VERSION="unknown"
|
||||
OS_PRETTY="Unknown OS"
|
||||
fi
|
||||
|
||||
# Detect architecture
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64|amd64) ARCH="x86_64" ;;
|
||||
aarch64|arm64) ARCH="aarch64" ;;
|
||||
*) ARCH="unknown" ;;
|
||||
esac
|
||||
|
||||
log_verbose "Detected OS: $OS_PRETTY ($OS_NAME $OS_VERSION) on $ARCH"
|
||||
}
|
||||
|
||||
detect_simd_capabilities() {
|
||||
SIMD_AVX512=false
|
||||
SIMD_AVX2=false
|
||||
SIMD_NEON=false
|
||||
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
if grep -q "avx512f" /proc/cpuinfo 2>/dev/null; then
|
||||
SIMD_AVX512=true
|
||||
log_verbose "AVX-512 support detected"
|
||||
fi
|
||||
if grep -q "avx2" /proc/cpuinfo 2>/dev/null; then
|
||||
SIMD_AVX2=true
|
||||
log_verbose "AVX2 support detected"
|
||||
fi
|
||||
elif [ "$ARCH" = "aarch64" ]; then
|
||||
# ARM NEON is standard on aarch64
|
||||
SIMD_NEON=true
|
||||
log_verbose "NEON support detected (ARM64)"
|
||||
fi
|
||||
|
||||
# Determine best SIMD mode
|
||||
if [ "$SIMD_MODE" = "auto" ]; then
|
||||
if [ "$SIMD_AVX512" = true ]; then
|
||||
DETECTED_SIMD="avx512"
|
||||
elif [ "$SIMD_AVX2" = true ]; then
|
||||
DETECTED_SIMD="avx2"
|
||||
elif [ "$SIMD_NEON" = true ]; then
|
||||
DETECTED_SIMD="neon"
|
||||
else
|
||||
DETECTED_SIMD="scalar"
|
||||
fi
|
||||
log_verbose "Auto-detected SIMD mode: $DETECTED_SIMD"
|
||||
else
|
||||
DETECTED_SIMD="$SIMD_MODE"
|
||||
fi
|
||||
}
|
||||
|
||||
detect_postgresql() {
|
||||
# Try to find pg_config
|
||||
if [ -n "$PG_CONFIG" ] && [ -x "$PG_CONFIG" ]; then
|
||||
log_verbose "Using provided pg_config: $PG_CONFIG"
|
||||
else
|
||||
# Search for pg_config in common locations
|
||||
PG_CONFIG_PATHS=(
|
||||
"/usr/bin/pg_config"
|
||||
"/usr/local/bin/pg_config"
|
||||
"/usr/pgsql-${PG_VERSION:-16}/bin/pg_config"
|
||||
"/usr/lib/postgresql/${PG_VERSION:-16}/bin/pg_config"
|
||||
"/opt/homebrew/opt/postgresql@${PG_VERSION:-16}/bin/pg_config"
|
||||
"/Applications/Postgres.app/Contents/Versions/latest/bin/pg_config"
|
||||
)
|
||||
|
||||
for path in "${PG_CONFIG_PATHS[@]}"; do
|
||||
if [ -x "$path" ]; then
|
||||
PG_CONFIG="$path"
|
||||
log_verbose "Found pg_config: $PG_CONFIG"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Try system PATH
|
||||
if [ -z "$PG_CONFIG" ] && check_command pg_config; then
|
||||
PG_CONFIG=$(which pg_config)
|
||||
log_verbose "Found pg_config in PATH: $PG_CONFIG"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$PG_CONFIG" ] || [ ! -x "$PG_CONFIG" ]; then
|
||||
die "PostgreSQL pg_config not found. Please install PostgreSQL or specify --pg-config"
|
||||
fi
|
||||
|
||||
# Get PostgreSQL information
|
||||
PG_DETECTED_VERSION=$("$PG_CONFIG" --version | grep -oP '\d+' | head -1)
|
||||
PG_LIBDIR=$("$PG_CONFIG" --pkglibdir)
|
||||
PG_SHAREDIR=$("$PG_CONFIG" --sharedir)
|
||||
PG_INCLUDEDIR=$("$PG_CONFIG" --includedir-server)
|
||||
PG_BINDIR=$("$PG_CONFIG" --bindir)
|
||||
|
||||
if [ -n "$PG_VERSION" ] && [ "$PG_VERSION" != "$PG_DETECTED_VERSION" ]; then
|
||||
log_warning "Requested PG version $PG_VERSION but detected $PG_DETECTED_VERSION"
|
||||
fi
|
||||
PG_VERSION="$PG_DETECTED_VERSION"
|
||||
|
||||
log_info "PostgreSQL $PG_VERSION detected"
|
||||
log_verbose " Library dir: $PG_LIBDIR"
|
||||
log_verbose " Share dir: $PG_SHAREDIR"
|
||||
log_verbose " Include dir: $PG_INCLUDEDIR"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Dependency Checks
|
||||
# ============================================================================
|
||||
|
||||
check_dependencies() {
|
||||
log_info "Checking dependencies..."
|
||||
|
||||
local missing_deps=()
|
||||
|
||||
# Check for required tools
|
||||
if [ "$BUILD_FROM_SOURCE" = true ]; then
|
||||
if ! check_command rustc; then
|
||||
missing_deps+=("rust")
|
||||
else
|
||||
RUST_VERSION=$(rustc --version | cut -d' ' -f2)
|
||||
log_verbose "Rust version: $RUST_VERSION"
|
||||
fi
|
||||
|
||||
if ! check_command cargo; then
|
||||
missing_deps+=("cargo")
|
||||
fi
|
||||
|
||||
# Check for pgrx
|
||||
if ! cargo install --list 2>/dev/null | grep -q "cargo-pgrx"; then
|
||||
log_warning "cargo-pgrx not installed, will install during build"
|
||||
fi
|
||||
|
||||
# Check for build tools
|
||||
if ! check_command gcc && ! check_command clang; then
|
||||
missing_deps+=("gcc or clang")
|
||||
fi
|
||||
|
||||
if ! check_command make; then
|
||||
missing_deps+=("make")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ${#missing_deps[@]} -gt 0 ]; then
|
||||
log_error "Missing dependencies: ${missing_deps[*]}"
|
||||
log_info "Install missing dependencies with:"
|
||||
case "$OS_NAME" in
|
||||
ubuntu|debian)
|
||||
echo " sudo apt-get install ${missing_deps[*]}"
|
||||
if [[ " ${missing_deps[*]} " =~ " rust " ]]; then
|
||||
echo " curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
|
||||
fi
|
||||
;;
|
||||
centos|rhel|fedora)
|
||||
echo " sudo dnf install ${missing_deps[*]}"
|
||||
if [[ " ${missing_deps[*]} " =~ " rust " ]]; then
|
||||
echo " curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
|
||||
fi
|
||||
;;
|
||||
macos)
|
||||
echo " brew install ${missing_deps[*]}"
|
||||
if [[ " ${missing_deps[*]} " =~ " rust " ]]; then
|
||||
echo " curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "All dependencies satisfied"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Installation Functions
|
||||
# ============================================================================
|
||||
|
||||
build_from_source() {
|
||||
log_info "Building RuVector from source..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Ensure pgrx is installed
|
||||
if ! cargo install --list 2>/dev/null | grep -q "cargo-pgrx"; then
|
||||
log_info "Installing cargo-pgrx..."
|
||||
run_cmd cargo install cargo-pgrx --version "0.12.9" --locked
|
||||
fi
|
||||
|
||||
# Initialize pgrx for our PG version if needed
|
||||
if [ ! -f "$HOME/.pgrx/config.toml" ]; then
|
||||
log_info "Initializing pgrx..."
|
||||
run_cmd cargo pgrx init --pg${PG_VERSION} "$PG_CONFIG"
|
||||
fi
|
||||
|
||||
# Set SIMD features based on detection
|
||||
local FEATURES="pg${PG_VERSION}"
|
||||
case "$DETECTED_SIMD" in
|
||||
avx512) FEATURES="$FEATURES,simd-avx512" ;;
|
||||
avx2) FEATURES="$FEATURES,simd-avx2" ;;
|
||||
neon) FEATURES="$FEATURES,simd-neon" ;;
|
||||
*) FEATURES="$FEATURES,simd-auto" ;;
|
||||
esac
|
||||
|
||||
log_verbose "Building with features: $FEATURES"
|
||||
|
||||
# Build the extension
|
||||
log_info "Compiling extension (this may take a few minutes)..."
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_info "[DRY-RUN] Would run: cargo pgrx package --pg-config $PG_CONFIG"
|
||||
else
|
||||
cd "$PROJECT_ROOT/crates/ruvector-postgres"
|
||||
cargo pgrx package --pg-config "$PG_CONFIG"
|
||||
fi
|
||||
|
||||
# Set build output path
|
||||
BUILD_OUTPUT="$PROJECT_ROOT/target/release/ruvector-pg${PG_VERSION}"
|
||||
|
||||
log_success "Build completed"
|
||||
}
|
||||
|
||||
install_extension() {
|
||||
log_info "Installing RuVector extension..."
|
||||
|
||||
local SO_FILE="${BUILD_OUTPUT}/usr/lib/postgresql/${PG_VERSION}/lib/ruvector.so"
|
||||
local CONTROL_FILE="${BUILD_OUTPUT}/usr/share/postgresql/${PG_VERSION}/extension/ruvector.control"
|
||||
local SQL_FILE="${PROJECT_ROOT}/crates/ruvector-postgres/sql/ruvector--${RUVECTOR_VERSION}.sql"
|
||||
|
||||
# Check build output exists
|
||||
if [ ! -f "$SO_FILE" ]; then
|
||||
die "Build output not found: $SO_FILE"
|
||||
fi
|
||||
|
||||
# Install shared library
|
||||
log_info "Installing shared library to $PG_LIBDIR..."
|
||||
run_cmd cp "$SO_FILE" "$PG_LIBDIR/"
|
||||
run_cmd chmod 755 "$PG_LIBDIR/ruvector.so"
|
||||
|
||||
# Install control file
|
||||
log_info "Installing control file to $PG_SHAREDIR/extension/..."
|
||||
run_cmd cp "$CONTROL_FILE" "$PG_SHAREDIR/extension/"
|
||||
|
||||
# Install SQL file
|
||||
log_info "Installing SQL file to $PG_SHAREDIR/extension/..."
|
||||
run_cmd cp "$SQL_FILE" "$PG_SHAREDIR/extension/"
|
||||
|
||||
log_success "Extension files installed"
|
||||
}
|
||||
|
||||
create_config() {
|
||||
log_info "Creating configuration..."
|
||||
|
||||
local CONFIG_DIR="$PG_SHAREDIR/extension"
|
||||
local CONFIG_OUT="$CONFIG_DIR/ruvector.conf"
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_info "[DRY-RUN] Would create config at: $CONFIG_OUT"
|
||||
return 0
|
||||
fi
|
||||
|
||||
cat > "$CONFIG_OUT" << EOF
|
||||
# RuVector PostgreSQL Extension Configuration
|
||||
# Generated by installer on $(date)
|
||||
|
||||
# =============================================================================
|
||||
# SIMD Configuration
|
||||
# =============================================================================
|
||||
# Detected SIMD capabilities: $DETECTED_SIMD
|
||||
# Options: auto, avx512, avx2, neon, scalar
|
||||
#ruvector.simd_mode = 'auto'
|
||||
|
||||
# =============================================================================
|
||||
# Memory Configuration
|
||||
# =============================================================================
|
||||
# Maximum memory for vector operations (in MB)
|
||||
#ruvector.max_memory_mb = 1024
|
||||
|
||||
# Enable memory pooling for better performance
|
||||
#ruvector.enable_memory_pool = on
|
||||
|
||||
# =============================================================================
|
||||
# Index Configuration
|
||||
# =============================================================================
|
||||
# Default HNSW index parameters
|
||||
#ruvector.hnsw_ef_construction = 64
|
||||
#ruvector.hnsw_m = 16
|
||||
#ruvector.hnsw_ef_search = 40
|
||||
|
||||
# Default IVF-Flat index parameters
|
||||
#ruvector.ivfflat_lists = 100
|
||||
#ruvector.ivfflat_probes = 10
|
||||
|
||||
# =============================================================================
|
||||
# Distance Calculation
|
||||
# =============================================================================
|
||||
# Enable parallel distance computation for large batches
|
||||
#ruvector.parallel_distance = on
|
||||
|
||||
# Minimum batch size for parallel processing
|
||||
#ruvector.parallel_min_batch = 1000
|
||||
|
||||
# =============================================================================
|
||||
# Quantization
|
||||
# =============================================================================
|
||||
# Enable product quantization for large datasets
|
||||
#ruvector.enable_pq = off
|
||||
|
||||
# Product quantization parameters
|
||||
#ruvector.pq_m = 8
|
||||
#ruvector.pq_nbits = 8
|
||||
|
||||
# =============================================================================
|
||||
# Logging
|
||||
# =============================================================================
|
||||
# Log level: debug, info, warning, error
|
||||
#ruvector.log_level = 'info'
|
||||
|
||||
# Log SIMD operations (for debugging)
|
||||
#ruvector.log_simd = off
|
||||
EOF
|
||||
|
||||
log_success "Configuration created at: $CONFIG_OUT"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Testing Functions
|
||||
# ============================================================================
|
||||
|
||||
run_tests() {
|
||||
if [ "$SKIP_TESTS" = true ]; then
|
||||
log_warning "Skipping installation tests"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Running installation tests..."
|
||||
|
||||
# Find psql
|
||||
local PSQL="${PG_BINDIR}/psql"
|
||||
if [ ! -x "$PSQL" ]; then
|
||||
PSQL=$(which psql 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
if [ -z "$PSQL" ] || [ ! -x "$PSQL" ]; then
|
||||
log_warning "psql not found, skipping tests"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Create test database
|
||||
local TEST_DB="ruvector_test_$$"
|
||||
|
||||
log_verbose "Creating test database: $TEST_DB"
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
log_info "[DRY-RUN] Would run installation tests"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Try to connect and run tests
|
||||
local TEST_RESULT=0
|
||||
|
||||
# Use postgres user or current user
|
||||
local PG_USER="${PGUSER:-postgres}"
|
||||
|
||||
# Create test script
|
||||
local TEST_SCRIPT=$(mktemp)
|
||||
cat > "$TEST_SCRIPT" << 'EOSQL'
|
||||
-- RuVector Installation Test Suite
|
||||
|
||||
-- Test 1: Create extension
|
||||
CREATE EXTENSION IF NOT EXISTS ruvector;
|
||||
SELECT 'Test 1: Extension created' AS result;
|
||||
|
||||
-- Test 2: Create table with ruvector column
|
||||
CREATE TABLE test_vectors (id serial PRIMARY KEY, embedding ruvector);
|
||||
SELECT 'Test 2: Table created' AS result;
|
||||
|
||||
-- Test 3: Insert vectors
|
||||
INSERT INTO test_vectors (embedding) VALUES
|
||||
('[1,2,3]'),
|
||||
('[4,5,6]'),
|
||||
('[7,8,9]');
|
||||
SELECT 'Test 3: Vectors inserted' AS result;
|
||||
|
||||
-- Test 4: Read vectors from storage
|
||||
SELECT count(*) AS vector_count FROM test_vectors;
|
||||
|
||||
-- Test 5: Distance calculations
|
||||
SELECT id, embedding <-> '[1,1,1]'::ruvector AS l2_dist
|
||||
FROM test_vectors ORDER BY l2_dist LIMIT 3;
|
||||
SELECT 'Test 5: Distance calculations work' AS result;
|
||||
|
||||
-- Test 6: Cosine distance
|
||||
SELECT id, embedding <=> '[1,1,1]'::ruvector AS cosine_dist
|
||||
FROM test_vectors ORDER BY cosine_dist LIMIT 3;
|
||||
SELECT 'Test 6: Cosine distance works' AS result;
|
||||
|
||||
-- Test 7: Vector dimensions
|
||||
SELECT ruvector_dims('[1,2,3,4,5]'::ruvector) AS dims;
|
||||
|
||||
-- Test 8: Vector normalization
|
||||
SELECT ruvector_norm('[3,4]'::ruvector) AS norm;
|
||||
|
||||
-- Cleanup
|
||||
DROP TABLE test_vectors;
|
||||
DROP EXTENSION ruvector CASCADE;
|
||||
SELECT 'All tests passed!' AS final_result;
|
||||
EOSQL
|
||||
|
||||
# Run tests
|
||||
if su - "$PG_USER" -c "createdb $TEST_DB" 2>/dev/null || createdb "$TEST_DB" 2>/dev/null; then
|
||||
if su - "$PG_USER" -c "$PSQL -d $TEST_DB -f $TEST_SCRIPT" 2>&1 || \
|
||||
$PSQL -d "$TEST_DB" -f "$TEST_SCRIPT" 2>&1; then
|
||||
log_success "All installation tests passed"
|
||||
else
|
||||
log_error "Some tests failed"
|
||||
TEST_RESULT=1
|
||||
fi
|
||||
|
||||
# Cleanup test database
|
||||
su - "$PG_USER" -c "dropdb $TEST_DB" 2>/dev/null || dropdb "$TEST_DB" 2>/dev/null || true
|
||||
else
|
||||
log_warning "Could not create test database, skipping detailed tests"
|
||||
|
||||
# Try simpler test
|
||||
log_info "Attempting basic connectivity test..."
|
||||
if su - "$PG_USER" -c "$PSQL -c 'SELECT 1'" 2>/dev/null || \
|
||||
$PSQL -c 'SELECT 1' 2>/dev/null; then
|
||||
log_success "PostgreSQL connectivity OK"
|
||||
else
|
||||
log_warning "Could not connect to PostgreSQL"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f "$TEST_SCRIPT"
|
||||
return $TEST_RESULT
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Uninstall Functions
|
||||
# ============================================================================
|
||||
|
||||
uninstall_extension() {
|
||||
log_info "Uninstalling RuVector extension..."
|
||||
|
||||
# Remove files
|
||||
local files_to_remove=(
|
||||
"$PG_LIBDIR/ruvector.so"
|
||||
"$PG_SHAREDIR/extension/ruvector.control"
|
||||
"$PG_SHAREDIR/extension/ruvector--${RUVECTOR_VERSION}.sql"
|
||||
"$PG_SHAREDIR/extension/ruvector.conf"
|
||||
)
|
||||
|
||||
for f in "${files_to_remove[@]}"; do
|
||||
if [ -f "$f" ]; then
|
||||
log_verbose "Removing: $f"
|
||||
run_cmd rm -f "$f"
|
||||
fi
|
||||
done
|
||||
|
||||
log_success "RuVector uninstalled"
|
||||
log_warning "Note: You may need to DROP EXTENSION ruvector in databases where it was created"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Main Installation Flow
|
||||
# ============================================================================
|
||||
|
||||
show_help() {
|
||||
cat << EOF
|
||||
RuVector PostgreSQL Extension Installer v${RUVECTOR_VERSION}
|
||||
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Options:
|
||||
--pg-version VERSION PostgreSQL version (14, 15, 16, 17)
|
||||
--pg-config PATH Path to pg_config binary
|
||||
--build-from-source Build from source (required for now)
|
||||
--simd MODE SIMD mode: auto, avx512, avx2, neon, scalar
|
||||
--prefix PATH Installation prefix (default: auto-detect)
|
||||
--config FILE Configuration file path
|
||||
--skip-tests Skip installation tests
|
||||
--uninstall Uninstall RuVector
|
||||
--upgrade Upgrade existing installation
|
||||
--dry-run Show what would be done
|
||||
--verbose Verbose output
|
||||
--help Show this help
|
||||
|
||||
Examples:
|
||||
# Install with auto-detection
|
||||
$0 --build-from-source
|
||||
|
||||
# Install for specific PostgreSQL version
|
||||
$0 --build-from-source --pg-version 16
|
||||
|
||||
# Install with specific pg_config
|
||||
$0 --build-from-source --pg-config /usr/pgsql-16/bin/pg_config
|
||||
|
||||
# Uninstall
|
||||
$0 --uninstall --pg-config /usr/bin/pg_config
|
||||
|
||||
# Dry run to see what would happen
|
||||
$0 --build-from-source --dry-run --verbose
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--pg-version)
|
||||
PG_VERSION="$2"
|
||||
shift 2
|
||||
;;
|
||||
--pg-config)
|
||||
PG_CONFIG="$2"
|
||||
shift 2
|
||||
;;
|
||||
--build-from-source)
|
||||
BUILD_FROM_SOURCE=true
|
||||
shift
|
||||
;;
|
||||
--simd)
|
||||
SIMD_MODE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--prefix)
|
||||
INSTALL_PREFIX="$2"
|
||||
shift 2
|
||||
;;
|
||||
--config)
|
||||
CONFIG_FILE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--skip-tests)
|
||||
SKIP_TESTS=true
|
||||
shift
|
||||
;;
|
||||
--uninstall)
|
||||
UNINSTALL=true
|
||||
shift
|
||||
;;
|
||||
--upgrade)
|
||||
UPGRADE=true
|
||||
shift
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
--verbose|-v)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
die "Unknown option: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
echo ""
|
||||
echo "╔═══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ RuVector PostgreSQL Extension Installer ║"
|
||||
echo "║ High-Performance Vector Similarity Search ║"
|
||||
echo "║ Version ${RUVECTOR_VERSION} ║"
|
||||
echo "╚═══════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
# Detect environment
|
||||
detect_os
|
||||
detect_simd_capabilities
|
||||
detect_postgresql
|
||||
|
||||
echo ""
|
||||
log_info "Environment Summary:"
|
||||
echo " OS: $OS_PRETTY"
|
||||
echo " Arch: $ARCH"
|
||||
echo " SIMD: $DETECTED_SIMD"
|
||||
echo " PostgreSQL: $PG_VERSION"
|
||||
echo " pg_config: $PG_CONFIG"
|
||||
echo ""
|
||||
|
||||
# Handle uninstall
|
||||
if [ "$UNINSTALL" = true ]; then
|
||||
uninstall_extension
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check dependencies
|
||||
check_dependencies
|
||||
|
||||
# Build from source (currently only option)
|
||||
if [ "$BUILD_FROM_SOURCE" = true ]; then
|
||||
build_from_source
|
||||
else
|
||||
log_warning "Pre-built binaries not yet available"
|
||||
log_info "Building from source..."
|
||||
BUILD_FROM_SOURCE=true
|
||||
build_from_source
|
||||
fi
|
||||
|
||||
# Install extension
|
||||
install_extension
|
||||
|
||||
# Create configuration
|
||||
create_config
|
||||
|
||||
# Run tests
|
||||
run_tests
|
||||
|
||||
echo ""
|
||||
log_success "RuVector installation complete!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Connect to your database: psql -d your_database"
|
||||
echo " 2. Create the extension: CREATE EXTENSION ruvector;"
|
||||
echo " 3. Create a table with vectors:"
|
||||
echo " CREATE TABLE items (id serial, embedding ruvector);"
|
||||
echo " 4. Insert vectors:"
|
||||
echo " INSERT INTO items (embedding) VALUES ('[1,2,3]');"
|
||||
echo " 5. Query with similarity search:"
|
||||
echo " SELECT * FROM items ORDER BY embedding <-> '[1,1,1]' LIMIT 10;"
|
||||
echo ""
|
||||
echo "Documentation: https://github.com/ruvnet/ruvector"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Run main
|
||||
main "$@"
|
||||
90
vendor/ruvector/crates/ruvector-postgres/install/quick-start.sh
vendored
Executable file
90
vendor/ruvector/crates/ruvector-postgres/install/quick-start.sh
vendored
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# RuVector Quick Start Installer
|
||||
# Auto-detects platform and runs appropriate setup
|
||||
#
|
||||
# Usage: curl -sSL https://raw.githubusercontent.com/ruvnet/ruvector/main/install/quick-start.sh | bash
|
||||
# or: ./quick-start.sh [PG_VERSION]
|
||||
#
|
||||
set -e
|
||||
|
||||
PG_VERSION="${1:-16}"
|
||||
|
||||
echo ""
|
||||
echo "╔═══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ RuVector Quick Start Installer ║"
|
||||
echo "╚═══════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
# Detect OS
|
||||
detect_os() {
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
echo "macos"
|
||||
elif [ -f /etc/debian_version ]; then
|
||||
echo "debian"
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
echo "rhel"
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
OS=$(detect_os)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" || SCRIPT_DIR="."
|
||||
|
||||
echo "Detected OS: $OS"
|
||||
echo "PostgreSQL version: $PG_VERSION"
|
||||
echo ""
|
||||
|
||||
case "$OS" in
|
||||
debian)
|
||||
echo "Running Debian/Ubuntu setup..."
|
||||
if [ -f "$SCRIPT_DIR/scripts/setup-debian.sh" ]; then
|
||||
bash "$SCRIPT_DIR/scripts/setup-debian.sh" "$PG_VERSION"
|
||||
else
|
||||
echo "Downloading setup script..."
|
||||
curl -sSL https://raw.githubusercontent.com/ruvnet/ruvector/main/install/scripts/setup-debian.sh | bash -s "$PG_VERSION"
|
||||
fi
|
||||
;;
|
||||
rhel)
|
||||
echo "Running RHEL/CentOS setup..."
|
||||
if [ -f "$SCRIPT_DIR/scripts/setup-rhel.sh" ]; then
|
||||
bash "$SCRIPT_DIR/scripts/setup-rhel.sh" "$PG_VERSION"
|
||||
else
|
||||
echo "Downloading setup script..."
|
||||
curl -sSL https://raw.githubusercontent.com/ruvnet/ruvector/main/install/scripts/setup-rhel.sh | bash -s "$PG_VERSION"
|
||||
fi
|
||||
;;
|
||||
macos)
|
||||
echo "Running macOS setup..."
|
||||
if [ -f "$SCRIPT_DIR/scripts/setup-macos.sh" ]; then
|
||||
bash "$SCRIPT_DIR/scripts/setup-macos.sh" "$PG_VERSION"
|
||||
else
|
||||
echo "Downloading setup script..."
|
||||
curl -sSL https://raw.githubusercontent.com/ruvnet/ruvector/main/install/scripts/setup-macos.sh | bash -s "$PG_VERSION"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported OS. Please install dependencies manually."
|
||||
echo ""
|
||||
echo "Required dependencies:"
|
||||
echo " - Rust (rustup.rs)"
|
||||
echo " - PostgreSQL $PG_VERSION with development headers"
|
||||
echo " - Build tools (gcc/clang, make, pkg-config)"
|
||||
echo " - cargo-pgrx (cargo install cargo-pgrx)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Dependencies installed! Now clone and build RuVector:"
|
||||
echo ""
|
||||
echo " git clone https://github.com/ruvnet/ruvector.git"
|
||||
echo " cd ruvector"
|
||||
echo " ./install/install.sh --build-from-source --pg-version $PG_VERSION"
|
||||
echo ""
|
||||
echo "Or for a dry run first:"
|
||||
echo " ./install/install.sh --build-from-source --dry-run --verbose"
|
||||
echo ""
|
||||
80
vendor/ruvector/crates/ruvector-postgres/install/scripts/setup-debian.sh
vendored
Executable file
80
vendor/ruvector/crates/ruvector-postgres/install/scripts/setup-debian.sh
vendored
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# RuVector Setup Script for Debian/Ubuntu
|
||||
# Installs all required dependencies for building RuVector
|
||||
#
|
||||
set -e
|
||||
|
||||
echo "RuVector Dependency Setup for Debian/Ubuntu"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
SUDO="sudo"
|
||||
else
|
||||
SUDO=""
|
||||
fi
|
||||
|
||||
# Update package lists
|
||||
echo "Updating package lists..."
|
||||
$SUDO apt-get update
|
||||
|
||||
# Install basic build tools
|
||||
echo "Installing build tools..."
|
||||
$SUDO apt-get install -y \
|
||||
build-essential \
|
||||
pkg-config \
|
||||
libssl-dev \
|
||||
libclang-dev \
|
||||
clang \
|
||||
cmake \
|
||||
git \
|
||||
curl \
|
||||
ca-certificates
|
||||
|
||||
# Determine PostgreSQL version to install
|
||||
PG_VERSION="${1:-16}"
|
||||
echo "Setting up PostgreSQL $PG_VERSION..."
|
||||
|
||||
# Add PostgreSQL repository
|
||||
if ! grep -q "apt.postgresql.org" /etc/apt/sources.list.d/*.list 2>/dev/null; then
|
||||
echo "Adding PostgreSQL APT repository..."
|
||||
$SUDO install -d /usr/share/postgresql-common/pgdg
|
||||
$SUDO curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail \
|
||||
https://www.postgresql.org/media/keys/ACCC4CF8.asc
|
||||
$SUDO sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
|
||||
https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > \
|
||||
/etc/apt/sources.list.d/pgdg.list'
|
||||
$SUDO apt-get update
|
||||
fi
|
||||
|
||||
# Install PostgreSQL
|
||||
echo "Installing PostgreSQL $PG_VERSION..."
|
||||
$SUDO apt-get install -y \
|
||||
"postgresql-$PG_VERSION" \
|
||||
"postgresql-server-dev-$PG_VERSION"
|
||||
|
||||
# Install Rust if not present
|
||||
if ! command -v rustc &> /dev/null; then
|
||||
echo "Installing Rust..."
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source "$HOME/.cargo/env"
|
||||
fi
|
||||
|
||||
# Install cargo-pgrx
|
||||
echo "Installing cargo-pgrx..."
|
||||
cargo install cargo-pgrx --version "0.12.9" --locked
|
||||
|
||||
# Initialize pgrx
|
||||
echo "Initializing pgrx for PostgreSQL $PG_VERSION..."
|
||||
cargo pgrx init --pg$PG_VERSION "/usr/lib/postgresql/$PG_VERSION/bin/pg_config"
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Setup complete!"
|
||||
echo ""
|
||||
echo "You can now build RuVector with:"
|
||||
echo " cd /path/to/ruvector"
|
||||
echo " ./install/install.sh --build-from-source --pg-version $PG_VERSION"
|
||||
echo ""
|
||||
84
vendor/ruvector/crates/ruvector-postgres/install/scripts/setup-macos.sh
vendored
Executable file
84
vendor/ruvector/crates/ruvector-postgres/install/scripts/setup-macos.sh
vendored
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# RuVector Setup Script for macOS
|
||||
# Installs all required dependencies for building RuVector
|
||||
#
|
||||
set -e
|
||||
|
||||
echo "RuVector Dependency Setup for macOS"
|
||||
echo "===================================="
|
||||
echo ""
|
||||
|
||||
# Check for Homebrew
|
||||
if ! command -v brew &> /dev/null; then
|
||||
echo "Installing Homebrew..."
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
|
||||
# Add to PATH for Apple Silicon Macs
|
||||
if [ -f "/opt/homebrew/bin/brew" ]; then
|
||||
eval "$(/opt/homebrew/bin/brew shellenv)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update Homebrew
|
||||
echo "Updating Homebrew..."
|
||||
brew update
|
||||
|
||||
# Install build tools
|
||||
echo "Installing build tools..."
|
||||
brew install \
|
||||
pkg-config \
|
||||
openssl \
|
||||
cmake \
|
||||
git \
|
||||
curl
|
||||
|
||||
# Determine PostgreSQL version to install
|
||||
PG_VERSION="${1:-16}"
|
||||
echo "Setting up PostgreSQL $PG_VERSION..."
|
||||
|
||||
# Install PostgreSQL
|
||||
echo "Installing PostgreSQL $PG_VERSION..."
|
||||
brew install "postgresql@$PG_VERSION"
|
||||
|
||||
# Link PostgreSQL
|
||||
brew link "postgresql@$PG_VERSION" --force 2>/dev/null || true
|
||||
|
||||
# Add PostgreSQL to PATH
|
||||
PG_PATH="/opt/homebrew/opt/postgresql@$PG_VERSION/bin"
|
||||
if [ ! -d "$PG_PATH" ]; then
|
||||
PG_PATH="/usr/local/opt/postgresql@$PG_VERSION/bin"
|
||||
fi
|
||||
|
||||
export PATH="$PG_PATH:$PATH"
|
||||
|
||||
# Start PostgreSQL service
|
||||
echo "Starting PostgreSQL service..."
|
||||
brew services start "postgresql@$PG_VERSION"
|
||||
|
||||
# Install Rust if not present
|
||||
if ! command -v rustc &> /dev/null; then
|
||||
echo "Installing Rust..."
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source "$HOME/.cargo/env"
|
||||
fi
|
||||
|
||||
# Install cargo-pgrx
|
||||
echo "Installing cargo-pgrx..."
|
||||
cargo install cargo-pgrx --version "0.12.9" --locked
|
||||
|
||||
# Initialize pgrx
|
||||
echo "Initializing pgrx for PostgreSQL $PG_VERSION..."
|
||||
cargo pgrx init --pg$PG_VERSION "$PG_PATH/pg_config"
|
||||
|
||||
echo ""
|
||||
echo "===================================="
|
||||
echo "Setup complete!"
|
||||
echo ""
|
||||
echo "Add PostgreSQL to your PATH:"
|
||||
echo " export PATH=\"$PG_PATH:\$PATH\""
|
||||
echo ""
|
||||
echo "You can now build RuVector with:"
|
||||
echo " cd /path/to/ruvector"
|
||||
echo " ./install/install.sh --build-from-source --pg-version $PG_VERSION"
|
||||
echo ""
|
||||
114
vendor/ruvector/crates/ruvector-postgres/install/scripts/setup-rhel.sh
vendored
Executable file
114
vendor/ruvector/crates/ruvector-postgres/install/scripts/setup-rhel.sh
vendored
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# RuVector Setup Script for RHEL/CentOS/Fedora
|
||||
# Installs all required dependencies for building RuVector
|
||||
#
|
||||
set -e
|
||||
|
||||
echo "RuVector Dependency Setup for RHEL/CentOS/Fedora"
|
||||
echo "================================================="
|
||||
echo ""
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
SUDO="sudo"
|
||||
else
|
||||
SUDO=""
|
||||
fi
|
||||
|
||||
# Detect distro
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
DISTRO="$ID"
|
||||
VERSION="$VERSION_ID"
|
||||
else
|
||||
DISTRO="unknown"
|
||||
fi
|
||||
|
||||
echo "Detected: $DISTRO $VERSION"
|
||||
|
||||
# Determine package manager
|
||||
if command -v dnf &> /dev/null; then
|
||||
PKG_MGR="dnf"
|
||||
elif command -v yum &> /dev/null; then
|
||||
PKG_MGR="yum"
|
||||
else
|
||||
echo "Error: Neither dnf nor yum found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install EPEL if needed (for CentOS/RHEL)
|
||||
if [[ "$DISTRO" == "centos" || "$DISTRO" == "rhel" ]]; then
|
||||
echo "Installing EPEL repository..."
|
||||
$SUDO $PKG_MGR install -y epel-release
|
||||
fi
|
||||
|
||||
# Install development tools
|
||||
echo "Installing development tools..."
|
||||
$SUDO $PKG_MGR groupinstall -y "Development Tools"
|
||||
$SUDO $PKG_MGR install -y \
|
||||
openssl-devel \
|
||||
clang \
|
||||
clang-devel \
|
||||
llvm-devel \
|
||||
cmake \
|
||||
git \
|
||||
curl \
|
||||
ca-certificates
|
||||
|
||||
# Determine PostgreSQL version to install
|
||||
PG_VERSION="${1:-16}"
|
||||
echo "Setting up PostgreSQL $PG_VERSION..."
|
||||
|
||||
# Add PostgreSQL repository
|
||||
if ! $PKG_MGR repolist | grep -q pgdg; then
|
||||
echo "Adding PostgreSQL repository..."
|
||||
$SUDO $PKG_MGR install -y \
|
||||
"https://download.postgresql.org/pub/repos/yum/reporpms/EL-${VERSION%%.*}-x86_64/pgdg-redhat-repo-latest.noarch.rpm"
|
||||
fi
|
||||
|
||||
# Disable built-in PostgreSQL module (for RHEL 8+)
|
||||
if [[ "$VERSION" =~ ^8 || "$VERSION" =~ ^9 ]]; then
|
||||
$SUDO dnf -qy module disable postgresql 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Install PostgreSQL
|
||||
echo "Installing PostgreSQL $PG_VERSION..."
|
||||
$SUDO $PKG_MGR install -y \
|
||||
"postgresql${PG_VERSION}-server" \
|
||||
"postgresql${PG_VERSION}-devel"
|
||||
|
||||
# Initialize PostgreSQL if needed
|
||||
if [ ! -f "/var/lib/pgsql/${PG_VERSION}/data/postgresql.conf" ]; then
|
||||
echo "Initializing PostgreSQL database..."
|
||||
$SUDO "/usr/pgsql-${PG_VERSION}/bin/postgresql-${PG_VERSION}-setup" initdb
|
||||
fi
|
||||
|
||||
# Start PostgreSQL
|
||||
echo "Starting PostgreSQL..."
|
||||
$SUDO systemctl enable "postgresql-${PG_VERSION}"
|
||||
$SUDO systemctl start "postgresql-${PG_VERSION}"
|
||||
|
||||
# Install Rust if not present
|
||||
if ! command -v rustc &> /dev/null; then
|
||||
echo "Installing Rust..."
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source "$HOME/.cargo/env"
|
||||
fi
|
||||
|
||||
# Install cargo-pgrx
|
||||
echo "Installing cargo-pgrx..."
|
||||
cargo install cargo-pgrx --version "0.12.9" --locked
|
||||
|
||||
# Initialize pgrx
|
||||
echo "Initializing pgrx for PostgreSQL $PG_VERSION..."
|
||||
cargo pgrx init --pg$PG_VERSION "/usr/pgsql-${PG_VERSION}/bin/pg_config"
|
||||
|
||||
echo ""
|
||||
echo "================================================="
|
||||
echo "Setup complete!"
|
||||
echo ""
|
||||
echo "You can now build RuVector with:"
|
||||
echo " cd /path/to/ruvector"
|
||||
echo " ./install/install.sh --build-from-source --pg-version $PG_VERSION"
|
||||
echo ""
|
||||
490
vendor/ruvector/crates/ruvector-postgres/install/tests/verify_installation.sh
vendored
Executable file
490
vendor/ruvector/crates/ruvector-postgres/install/tests/verify_installation.sh
vendored
Executable file
@@ -0,0 +1,490 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# RuVector Installation Verification Script
|
||||
# Comprehensive test suite to verify the extension works correctly
|
||||
#
|
||||
# Usage: ./verify_installation.sh [OPTIONS]
|
||||
#
|
||||
# Options:
|
||||
# --database DB Database to use for testing (default: creates temp db)
|
||||
# --host HOST PostgreSQL host (default: localhost)
|
||||
# --port PORT PostgreSQL port (default: 5432)
|
||||
# --user USER PostgreSQL user (default: postgres)
|
||||
# --verbose Show detailed output
|
||||
# --benchmark Run performance benchmarks
|
||||
# --cleanup Clean up test artifacts
|
||||
#
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
TEST_DB=""
|
||||
PG_HOST="${PGHOST:-localhost}"
|
||||
PG_PORT="${PGPORT:-5432}"
|
||||
PG_USER="${PGUSER:-postgres}"
|
||||
VERBOSE=false
|
||||
BENCHMARK=false
|
||||
CLEANUP=false
|
||||
TEMP_DB=false
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Counters
|
||||
TESTS_PASSED=0
|
||||
TESTS_FAILED=0
|
||||
TESTS_SKIPPED=0
|
||||
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[PASS]${NC} $1"; }
|
||||
log_fail() { echo -e "${RED}[FAIL]${NC} $1"; }
|
||||
log_skip() { echo -e "${YELLOW}[SKIP]${NC} $1"; }
|
||||
log_verbose() { [ "$VERBOSE" = true ] && echo -e "[DEBUG] $1" || true; }
|
||||
|
||||
run_test() {
|
||||
local test_name="$1"
|
||||
local test_sql="$2"
|
||||
local expected="$3"
|
||||
|
||||
log_verbose "Running: $test_sql"
|
||||
|
||||
local result
|
||||
if result=$(psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" \
|
||||
-tAc "$test_sql" 2>&1); then
|
||||
if [ -z "$expected" ] || [[ "$result" == *"$expected"* ]]; then
|
||||
log_success "$test_name"
|
||||
((TESTS_PASSED++))
|
||||
return 0
|
||||
else
|
||||
log_fail "$test_name (expected: $expected, got: $result)"
|
||||
((TESTS_FAILED++))
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_fail "$test_name (error: $result)"
|
||||
((TESTS_FAILED++))
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_test_numeric() {
|
||||
local test_name="$1"
|
||||
local test_sql="$2"
|
||||
local expected="$3"
|
||||
local tolerance="${4:-0.001}"
|
||||
|
||||
log_verbose "Running: $test_sql"
|
||||
|
||||
local result
|
||||
if result=$(psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" \
|
||||
-tAc "$test_sql" 2>&1); then
|
||||
# Compare with tolerance
|
||||
local diff=$(echo "$result - $expected" | bc -l 2>/dev/null | tr -d '-')
|
||||
if [ -n "$diff" ] && (( $(echo "$diff <= $tolerance" | bc -l) )); then
|
||||
log_success "$test_name (got: $result)"
|
||||
((TESTS_PASSED++))
|
||||
return 0
|
||||
else
|
||||
log_fail "$test_name (expected: ~$expected, got: $result)"
|
||||
((TESTS_FAILED++))
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_fail "$test_name (error: $result)"
|
||||
((TESTS_FAILED++))
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Test Suites
|
||||
# ============================================================================
|
||||
|
||||
test_extension_load() {
|
||||
echo ""
|
||||
echo "=== Extension Loading Tests ==="
|
||||
|
||||
run_test "Create extension" \
|
||||
"DROP EXTENSION IF EXISTS ruvector CASCADE; CREATE EXTENSION ruvector;" \
|
||||
""
|
||||
|
||||
run_test "Extension exists" \
|
||||
"SELECT extname FROM pg_extension WHERE extname = 'ruvector';" \
|
||||
"ruvector"
|
||||
|
||||
run_test "Check version" \
|
||||
"SELECT extversion FROM pg_extension WHERE extname = 'ruvector';" \
|
||||
"0.1.0"
|
||||
}
|
||||
|
||||
test_type_creation() {
|
||||
echo ""
|
||||
echo "=== Type Creation Tests ==="
|
||||
|
||||
run_test "Create table with ruvector" \
|
||||
"DROP TABLE IF EXISTS test_vec; CREATE TABLE test_vec (id serial, v ruvector);" \
|
||||
""
|
||||
|
||||
run_test "Create table with dimension constraint" \
|
||||
"DROP TABLE IF EXISTS test_vec_dim; CREATE TABLE test_vec_dim (id serial, v ruvector(128));" \
|
||||
""
|
||||
}
|
||||
|
||||
test_vector_io() {
|
||||
echo ""
|
||||
echo "=== Vector I/O Tests ==="
|
||||
|
||||
run_test "Insert vector" \
|
||||
"INSERT INTO test_vec (v) VALUES ('[1,2,3]') RETURNING id;" \
|
||||
"1"
|
||||
|
||||
run_test "Read vector" \
|
||||
"SELECT v FROM test_vec WHERE id = 1;" \
|
||||
"[1,2,3]"
|
||||
|
||||
run_test "Insert multiple vectors" \
|
||||
"INSERT INTO test_vec (v) VALUES ('[4,5,6]'), ('[7,8,9]'), ('[10,11,12]'); SELECT count(*) FROM test_vec;" \
|
||||
"4"
|
||||
|
||||
run_test "Insert high-dimensional vector" \
|
||||
"INSERT INTO test_vec (v) VALUES ('[' || array_to_string(array_agg(i::float4), ',') || ']') FROM generate_series(1, 128) i; SELECT count(*) FROM test_vec;" \
|
||||
"5"
|
||||
}
|
||||
|
||||
test_distance_functions() {
|
||||
echo ""
|
||||
echo "=== Distance Function Tests ==="
|
||||
|
||||
# L2 distance: sqrt((4-1)^2 + (5-2)^2 + (6-3)^2) = sqrt(27) = 5.196...
|
||||
run_test_numeric "L2 distance operator" \
|
||||
"SELECT '[1,2,3]'::ruvector <-> '[4,5,6]'::ruvector;" \
|
||||
"5.196" \
|
||||
"0.01"
|
||||
|
||||
# Cosine distance
|
||||
run_test_numeric "Cosine distance operator" \
|
||||
"SELECT '[1,0,0]'::ruvector <=> '[0,1,0]'::ruvector;" \
|
||||
"1.0" \
|
||||
"0.01"
|
||||
|
||||
# Inner product
|
||||
run_test_numeric "Inner product operator" \
|
||||
"SELECT '[1,2,3]'::ruvector <#> '[4,5,6]'::ruvector;" \
|
||||
"-32" \
|
||||
"0.01"
|
||||
|
||||
# Test stored vector distances
|
||||
run_test "Distance from stored vectors" \
|
||||
"SELECT id FROM test_vec ORDER BY v <-> '[1,1,1]'::ruvector LIMIT 1;" \
|
||||
"1"
|
||||
}
|
||||
|
||||
test_vector_functions() {
|
||||
echo ""
|
||||
echo "=== Vector Function Tests ==="
|
||||
|
||||
run_test "Get dimensions" \
|
||||
"SELECT ruvector_dims('[1,2,3,4,5]'::ruvector);" \
|
||||
"5"
|
||||
|
||||
run_test_numeric "Get norm" \
|
||||
"SELECT ruvector_norm('[3,4]'::ruvector);" \
|
||||
"5.0" \
|
||||
"0.001"
|
||||
|
||||
run_test "Normalize vector" \
|
||||
"SELECT ruvector_dims(ruvector_normalize('[1,2,3]'::ruvector));" \
|
||||
"3"
|
||||
|
||||
run_test_numeric "Normalized vector norm" \
|
||||
"SELECT ruvector_norm(ruvector_normalize('[3,4,0]'::ruvector));" \
|
||||
"1.0" \
|
||||
"0.001"
|
||||
}
|
||||
|
||||
test_vector_arithmetic() {
|
||||
echo ""
|
||||
echo "=== Vector Arithmetic Tests ==="
|
||||
|
||||
run_test "Vector addition" \
|
||||
"SELECT ruvector_add('[1,2,3]'::ruvector, '[4,5,6]'::ruvector);" \
|
||||
"[5,7,9]"
|
||||
|
||||
run_test "Vector subtraction" \
|
||||
"SELECT ruvector_sub('[4,5,6]'::ruvector, '[1,2,3]'::ruvector);" \
|
||||
"[3,3,3]"
|
||||
|
||||
run_test "Scalar multiplication" \
|
||||
"SELECT ruvector_mul_scalar('[1,2,3]'::ruvector, 2.0);" \
|
||||
"[2,4,6]"
|
||||
}
|
||||
|
||||
test_aggregate_operations() {
|
||||
echo ""
|
||||
echo "=== Aggregate Operation Tests ==="
|
||||
|
||||
run_test "Count vectors" \
|
||||
"SELECT count(*) FROM test_vec WHERE v <-> '[0,0,0]'::ruvector < 100;" \
|
||||
""
|
||||
|
||||
run_test "Min distance" \
|
||||
"SELECT count(*) FROM (SELECT min(v <-> '[1,1,1]'::ruvector) FROM test_vec) t;" \
|
||||
"1"
|
||||
|
||||
run_test "Nearest neighbor query" \
|
||||
"SELECT count(*) FROM (SELECT id FROM test_vec ORDER BY v <-> '[1,1,1]'::ruvector LIMIT 3) t;" \
|
||||
"3"
|
||||
}
|
||||
|
||||
test_temporal_functions() {
|
||||
echo ""
|
||||
echo "=== Temporal Function Tests ==="
|
||||
|
||||
run_test "Temporal delta" \
|
||||
"SELECT temporal_delta(ARRAY[2.0,4.0,6.0], ARRAY[1.0,2.0,3.0]);" \
|
||||
"{1,2,3}"
|
||||
|
||||
run_test "Temporal undelta" \
|
||||
"SELECT temporal_undelta(ARRAY[1.0,2.0,3.0], ARRAY[1.0,2.0,3.0]);" \
|
||||
"{2,4,6}"
|
||||
|
||||
run_test_numeric "Temporal EMA update" \
|
||||
"SELECT (temporal_ema_update(ARRAY[1.0], ARRAY[0.0], 0.5))[1];" \
|
||||
"0.5" \
|
||||
"0.001"
|
||||
}
|
||||
|
||||
test_attention_functions() {
|
||||
echo ""
|
||||
echo "=== Attention Function Tests ==="
|
||||
|
||||
run_test_numeric "Attention score" \
|
||||
"SELECT attention_score(ARRAY[1.0,0.0], ARRAY[1.0,0.0]);" \
|
||||
"0.707" \
|
||||
"0.01"
|
||||
|
||||
run_test "Attention softmax" \
|
||||
"SELECT array_length(attention_softmax(ARRAY[1.0, 2.0, 3.0]), 1);" \
|
||||
"3"
|
||||
|
||||
run_test "Attention init" \
|
||||
"SELECT array_length(attention_init(128), 1);" \
|
||||
"128"
|
||||
}
|
||||
|
||||
test_graph_functions() {
|
||||
echo ""
|
||||
echo "=== Graph Function Tests ==="
|
||||
|
||||
run_test_numeric "Graph edge similarity (identical)" \
|
||||
"SELECT graph_edge_similarity(ARRAY[1.0,0.0], ARRAY[1.0,0.0]);" \
|
||||
"1.0" \
|
||||
"0.001"
|
||||
|
||||
run_test_numeric "PageRank contribution" \
|
||||
"SELECT graph_pagerank_contribution(1.0, 4, 0.85);" \
|
||||
"0.2125" \
|
||||
"0.001"
|
||||
|
||||
run_test "Graph is connected" \
|
||||
"SELECT graph_is_connected(ARRAY[1.0,0.0], ARRAY[0.9,0.1], 0.9);" \
|
||||
"t"
|
||||
}
|
||||
|
||||
test_error_handling() {
|
||||
echo ""
|
||||
echo "=== Error Handling Tests ==="
|
||||
|
||||
# Dimension mismatch
|
||||
local result
|
||||
if result=$(psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" \
|
||||
-c "SELECT '[1,2,3]'::ruvector <-> '[1,2]'::ruvector;" 2>&1); then
|
||||
log_fail "Should reject dimension mismatch"
|
||||
((TESTS_FAILED++))
|
||||
else
|
||||
log_success "Rejects dimension mismatch"
|
||||
((TESTS_PASSED++))
|
||||
fi
|
||||
|
||||
# Invalid format
|
||||
if result=$(psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" \
|
||||
-c "SELECT 'invalid'::ruvector;" 2>&1); then
|
||||
log_fail "Should reject invalid format"
|
||||
((TESTS_FAILED++))
|
||||
else
|
||||
log_success "Rejects invalid format"
|
||||
((TESTS_PASSED++))
|
||||
fi
|
||||
}
|
||||
|
||||
run_benchmarks() {
|
||||
echo ""
|
||||
echo "=== Performance Benchmarks ==="
|
||||
|
||||
# Create benchmark table
|
||||
psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" -c "
|
||||
DROP TABLE IF EXISTS bench_vec;
|
||||
CREATE TABLE bench_vec (id serial PRIMARY KEY, embedding ruvector);
|
||||
" >/dev/null 2>&1
|
||||
|
||||
# Insert test data
|
||||
log_info "Generating 10,000 128-dimensional test vectors..."
|
||||
psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" -c "
|
||||
DO \$\$
|
||||
DECLARE
|
||||
i INTEGER;
|
||||
vec TEXT;
|
||||
j INTEGER;
|
||||
vals TEXT[];
|
||||
BEGIN
|
||||
FOR i IN 1..10000 LOOP
|
||||
vals := ARRAY[]::TEXT[];
|
||||
FOR j IN 1..128 LOOP
|
||||
vals := array_append(vals, (random() * 2 - 1)::float4::text);
|
||||
END LOOP;
|
||||
vec := '[' || array_to_string(vals, ',') || ']';
|
||||
INSERT INTO bench_vec (embedding) VALUES (vec::ruvector);
|
||||
END LOOP;
|
||||
END \$\$;
|
||||
" >/dev/null 2>&1
|
||||
|
||||
# Run benchmark
|
||||
log_info "Running nearest neighbor benchmark (10K vectors, 128 dims)..."
|
||||
local result
|
||||
result=$(psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" -c "
|
||||
EXPLAIN ANALYZE
|
||||
SELECT id, embedding <-> (SELECT embedding FROM bench_vec WHERE id = 1) AS dist
|
||||
FROM bench_vec
|
||||
ORDER BY dist
|
||||
LIMIT 10;
|
||||
" 2>&1)
|
||||
|
||||
# Extract execution time
|
||||
local exec_time=$(echo "$result" | grep -oP 'Execution Time: \K[\d.]+')
|
||||
if [ -n "$exec_time" ]; then
|
||||
log_success "Nearest neighbor query: ${exec_time}ms"
|
||||
|
||||
# Calculate throughput
|
||||
local throughput=$(echo "scale=2; 10000 / $exec_time * 1000" | bc)
|
||||
log_info "Throughput: ~${throughput} distance calculations/second"
|
||||
else
|
||||
log_info "Benchmark result:"
|
||||
echo "$result" | grep -E "(Execution Time|Planning Time|Seq Scan)"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" -c "
|
||||
DROP TABLE IF EXISTS bench_vec;
|
||||
" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
cleanup_tests() {
|
||||
log_info "Cleaning up test artifacts..."
|
||||
|
||||
psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$TEST_DB" -c "
|
||||
DROP TABLE IF EXISTS test_vec CASCADE;
|
||||
DROP TABLE IF EXISTS test_vec_dim CASCADE;
|
||||
DROP TABLE IF EXISTS bench_vec CASCADE;
|
||||
" >/dev/null 2>&1
|
||||
|
||||
if [ "$TEMP_DB" = true ]; then
|
||||
log_info "Dropping temporary database: $TEST_DB"
|
||||
dropdb -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" "$TEST_DB" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Main
|
||||
# ============================================================================
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--database) TEST_DB="$2"; shift 2 ;;
|
||||
--host) PG_HOST="$2"; shift 2 ;;
|
||||
--port) PG_PORT="$2"; shift 2 ;;
|
||||
--user) PG_USER="$2"; shift 2 ;;
|
||||
--verbose) VERBOSE=true; shift ;;
|
||||
--benchmark) BENCHMARK=true; shift ;;
|
||||
--cleanup) CLEANUP=true; shift ;;
|
||||
--help)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo "Options:"
|
||||
echo " --database DB Database to use for testing"
|
||||
echo " --host HOST PostgreSQL host (default: localhost)"
|
||||
echo " --port PORT PostgreSQL port (default: 5432)"
|
||||
echo " --user USER PostgreSQL user (default: postgres)"
|
||||
echo " --verbose Show detailed output"
|
||||
echo " --benchmark Run performance benchmarks"
|
||||
echo " --cleanup Clean up test artifacts"
|
||||
exit 0
|
||||
;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
echo ""
|
||||
echo "╔═══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ RuVector Installation Verification Suite ║"
|
||||
echo "╚═══════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
# Create temp database if needed
|
||||
if [ -z "$TEST_DB" ]; then
|
||||
TEST_DB="ruvector_verify_$$"
|
||||
TEMP_DB=true
|
||||
log_info "Creating temporary database: $TEST_DB"
|
||||
createdb -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" "$TEST_DB" || {
|
||||
log_fail "Could not create test database"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
# Set trap for cleanup
|
||||
trap cleanup_tests EXIT
|
||||
|
||||
# Run test suites
|
||||
test_extension_load
|
||||
test_type_creation
|
||||
test_vector_io
|
||||
test_distance_functions
|
||||
test_vector_functions
|
||||
test_vector_arithmetic
|
||||
test_aggregate_operations
|
||||
test_temporal_functions
|
||||
test_attention_functions
|
||||
test_graph_functions
|
||||
test_error_handling
|
||||
|
||||
if [ "$BENCHMARK" = true ]; then
|
||||
run_benchmarks
|
||||
fi
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo " TEST SUMMARY"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo -e " Passed: ${GREEN}${TESTS_PASSED}${NC}"
|
||||
echo -e " Failed: ${RED}${TESTS_FAILED}${NC}"
|
||||
echo -e " Skipped: ${YELLOW}${TESTS_SKIPPED}${NC}"
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
if [ "$TESTS_FAILED" -gt 0 ]; then
|
||||
log_fail "Some tests failed!"
|
||||
exit 1
|
||||
else
|
||||
log_success "All tests passed!"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user