diff --git a/packages/php-storage-driver-common/composer.json b/packages/php-storage-driver-common/composer.json index 2c3f401ff..ddf0d0340 100644 --- a/packages/php-storage-driver-common/composer.json +++ b/packages/php-storage-driver-common/composer.json @@ -50,7 +50,7 @@ "lock": false }, "scripts": { - "protobuf": "rm -rf ./generated/* && protoc $(find proto -iname \"*.proto\") --php_out=generated", + "protobuf": "rm -rf ./generated/* && protoc $(find proto -iname \"*.proto\") --php_out=generated --python_out=generated-py", "protobufTests": "rm -rf ./tests/generated/* && protoc $(find tests/proto -iname \"*.proto\") --php_out=tests/generated", "phplint": "parallel-lint -j 10 --exclude vendor --exclude bin .", "phpcs": "phpcs --extensions=php tests contract Shared --ignore=./tests/generated/*", diff --git a/packages/php-storage-driver-common/generated-py/README.md b/packages/php-storage-driver-common/generated-py/README.md new file mode 100644 index 000000000..997caba55 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/README.md @@ -0,0 +1,294 @@ +# Keboola Storage Driver - Python Protocol Buffers + +This directory contains automatically generated Python code from Protocol Buffer definitions for the Keboola Storage Driver. + +## Installation + +### 1. Install Dependencies + +```bash +pip install -r requirements.txt +``` + +Or install protobuf directly: + +```bash +pip install protobuf +``` + +### 2. Add to Python Path + +Add the `generated-py` directory to your Python path: + +```python +import sys +sys.path.insert(0, '/path/to/generated-py') +``` + +Or set the `PYTHONPATH` environment variable: + +```bash +export PYTHONPATH="/path/to/generated-py:$PYTHONPATH" +``` + +## Quick Start + +### Basic Usage + +```python +import sys +sys.path.insert(0, '/path/to/generated-py') + +from proto import common_pb2 + +# Create a driver request +request = common_pb2.DriverRequest() +request.features.append('my-feature') +request.runtimeOptions.runId = 'run-123' +request.runtimeOptions.queryTags['branchId'] = 'main' + +# Serialize to binary +binary_data = request.SerializeToString() + +# Deserialize from binary +request2 = common_pb2.DriverRequest() +request2.ParseFromString(binary_data) + +print(f"Run ID: {request2.runtimeOptions.runId}") +``` + +### Creating Table Commands + +```python +from proto import table_pb2 + +# Create a table +cmd = table_pb2.CreateTableCommand() +cmd.path.extend(['project-123', 'bucket-456']) +cmd.tableName = 'users' +cmd.primaryKeysNames.append('user_id') + +# Add column definition +col = cmd.columns.add() +col.name = 'user_id' +col.type = 'INTEGER' +col.nullable = False + +col = cmd.columns.add() +col.name = 'email' +col.type = 'STRING' +col.nullable = False +``` + +### Working with BigQuery Backend + +```python +from proto import table_pb2 +from proto.backend import bigQuery_pb2 + +# Create table with BigQuery-specific options +cmd = table_pb2.CreateTableCommand() +cmd.tableName = 'events' + +# Configure BigQuery metadata +bq_meta = table_pb2.CreateTableCommand.BigQueryTableMeta() +bq_meta.requirePartitionFilter = True + +# Set time partitioning +bq_meta.timePartitioning.type = 'DAY' +bq_meta.timePartitioning.field = 'event_timestamp' + +# Set clustering +bq_meta.clustering.fields.append('user_id') +bq_meta.clustering.fields.append('event_type') + +# Pack into the command's meta field +cmd.meta.Pack(bq_meta) +``` + +### JSON Serialization + +```python +from proto import common_pb2 +from google.protobuf import json_format + +# Create message +request = common_pb2.DriverRequest() +request.runtimeOptions.runId = 'test-123' + +# Convert to JSON +json_str = json_format.MessageToJson(request) +print(json_str) + +# Parse from JSON +request2 = common_pb2.DriverRequest() +json_format.Parse(json_str, request2) +``` + +## Available Modules + +### `proto.common_pb2` +Core message types: +- `DriverRequest` - Main request wrapper for all driver commands +- `DriverResponse` - Main response wrapper +- `RuntimeOptions` - Runtime configuration (runId, queryTags, meta) +- `LogMessage` - Structured logging messages (PSR-3 compliant) + +### `proto.table_pb2` +Table operations: +- `CreateTableCommand` / `DropTableCommand` +- `AddColumnCommand` / `AlterColumnCommand` / `DropColumnCommand` +- `AddPrimaryKeyCommand` / `DropPrimaryKeyCommand` +- `TableImportFromFileCommand` / `TableImportResponse` +- `TableImportFromTableCommand` +- `TableExportToFileCommand` / `TableExportToFileResponse` +- `PreviewTableCommand` / `PreviewTableResponse` +- `DeleteTableRowsCommand` / `DeleteTableRowsResponse` +- `ImportExportShared` - Shared types for import/export operations + +### `proto.bucket_pb2` +Bucket operations and management + +### `proto.workspace_pb2` +Workspace operations and management + +### `proto.project_pb2` +Project-level operations + +### `proto.credentials_pb2` +Credentials handling for different backends + +### `proto.info_pb2` +Information and metadata queries + +### `proto.executeQuery_pb2` +Query execution commands + +### `proto.backend_pb2` +Generic backend operations + +### `proto.backend.bigQuery_pb2` +BigQuery-specific types: +- `TimePartitioning` - Time-based partitioning configuration +- `RangePartitioning` - Range-based partitioning configuration +- `Clustering` - Clustering configuration + +## gRPC Server Example + +This package includes a complete example implementation of a gRPC server for the StorageDriverService. + +### Features + +- **Pure gRPC server** with command routing +- **5 example command handlers**: CreateTable, PreviewTable, ImportFromFile, ExecuteQuery, ObjectInfo +- **Mock storage backend** for demonstration +- **Client library** for easy interaction +- **Comprehensive documentation** and examples + +### Quick Start + +```bash +# Install gRPC dependencies +pip install -r requirements-grpc.txt + +# Start the server +python3 -m examples.grpc_server + +# In another terminal, run the examples +python3 -m examples.client.client_examples +``` + +### Usage Example + +```python +from examples.client.grpc_client import StorageDriverClient + +with StorageDriverClient("localhost:50051") as client: + # Create a table + client.create_table( + path=['my-project', 'my-bucket'], + table_name='users', + columns=[ + {'name': 'user_id', 'type': 'INTEGER', 'nullable': False}, + {'name': 'email', 'type': 'STRING', 'nullable': False}, + ], + primary_keys=['user_id'] + ) + + # Import data + response = client.import_from_file( + path=['my-project', 'my-bucket'], + table_name='users', + file_provider="S3", + file_path={'root': 'bucket', 'path': 'data', 'fileName': 'users.csv'} + ) + print(f"Imported {response.importedRowsCount} rows") + + # Preview data + preview = client.preview_table( + path=['my-project', 'my-bucket'], + table_name='users', + limit=10 + ) +``` + +### Documentation + +See **[examples/README.md](examples/README.md)** for complete documentation including: +- Architecture overview +- Adding new commands +- Integrating real backends (BigQuery, Snowflake, etc.) +- Production considerations +- Testing +- Troubleshooting + +## File Structure + +``` +generated-py/ +├── README.md # This file +├── requirements.txt # Python dependencies +└── proto/ + ├── __init__.py + ├── backend/ + │ ├── __init__.py + │ └── bigQuery_pb2.py # BigQuery backend types + ├── backend_pb2.py # Generic backend types + ├── bucket_pb2.py # Bucket operations + ├── common_pb2.py # Core request/response types + ├── credentials_pb2.py # Credentials management + ├── executeQuery_pb2.py # Query execution + ├── info_pb2.py # Information queries + ├── project_pb2.py # Project operations + ├── service_pb2.py # Service operations + ├── table_pb2.py # Table operations + └── workspace_pb2.py # Workspace operations +``` + +## Regenerating Python Code + +This directory is automatically generated from `.proto` files. To regenerate after updating proto definitions: + +```bash +cd /path/to/php-storage-driver-common +composer protobuf +``` + +Or run protoc directly: + +```bash +protoc $(find proto -iname "*.proto") --python_out=generated-py +``` + +**Note:** After regeneration, the `__init__.py` files, `requirements.txt`, and this `README.md` should be preserved or recreated. + +## Additional Resources + +- [Protocol Buffers Documentation](https://developers.google.com/protocol-buffers/docs/pythontutorial) +- [Python API Reference](https://developers.google.com/protocol-buffers/docs/reference/python-generated) + +## Version + +Generated from proto definitions in: `php-storage-driver-common/proto/` + +Python protobuf version required: `>=3.21.0` diff --git a/packages/php-storage-driver-common/generated-py/__init__.py b/packages/php-storage-driver-common/generated-py/__init__.py new file mode 100644 index 000000000..ae4b42b5f --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/__init__.py @@ -0,0 +1,10 @@ +""" +Keboola Storage Driver Protocol Buffers - Python Package + +This package contains automatically generated Python code from Protocol Buffer definitions. +These protocol buffers define the interface for Keboola Storage Driver commands and responses. + +Generated from: php-storage-driver-common proto definitions +""" + +__version__ = "1.0.0" diff --git a/packages/php-storage-driver-common/generated-py/examples/README.md b/packages/php-storage-driver-common/generated-py/examples/README.md new file mode 100644 index 000000000..40638d9e2 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/README.md @@ -0,0 +1,478 @@ +# StorageDriverService gRPC Server Example + +This directory contains an educational example implementation of the `StorageDriverService` as a pure gRPC server in Python. + +## Overview + +The implementation demonstrates: +- gRPC server setup and lifecycle management +- Command routing using `google.protobuf.Any` wrapper pattern +- Handler pattern for processing different command types +- Mock storage backend for demonstration +- Client library for easy interaction +- Error handling and logging patterns + +## Architecture + +``` +┌─────────────┐ ┌──────────────────┐ ┌───────────────┐ +│ Client │─────────▶│ gRPC Server │─────────▶│ Handlers │ +│ │ │ (Servicer) │ │ │ +└─────────────┘ └──────────────────┘ └───────┬───────┘ + │ + ▼ + ┌────────────────┐ + │ Mock Storage │ + │ Backend │ + └────────────────┘ +``` + +### Components + +1. **gRPC Server** (`grpc_server.py`) + - Implements `StorageDriverService` + - Routes commands to appropriate handlers + - Manages server lifecycle + +2. **Handlers** (`handlers/`) + - `base_handler.py` - Abstract base with common logic + - `table_handler.py` - Table operations (Create, Preview, Import) + - `query_handler.py` - Query execution + - `info_handler.py` - Metadata queries + +3. **Storage Backend** (`storage/mock_storage.py`) + - In-memory storage for demonstration + - Shows integration patterns for real backends + +4. **Client Library** (`client/grpc_client.py`) + - Convenient Python client wrapper + - Handles protobuf wrapping/unwrapping + +5. **Configuration** (`config.py`, `utils.py`) + - Server configuration + - Logging and utility functions + +## Prerequisites + +```bash +# Install dependencies +cd generated-py +pip install -r requirements-grpc.txt +``` + +Or use the provided virtual environment: +```bash +cd generated-py +source .venv/bin/activate # On Windows: .venv\Scripts\activate +``` + +## Quick Start + +### 1. Start the Server + +```bash +cd generated-py +python3 -m examples.grpc_server + +# Or with custom settings: +python3 -m examples.grpc_server --port 8080 --log-level DEBUG +``` + +The server will start on `localhost:50051` by default. + +### 2. Run the Client Examples + +In another terminal: + +```bash +cd generated-py +python3 -m examples.client.client_examples +``` + +This will run several examples demonstrating: +- Creating tables +- Importing data +- Previewing table data +- Executing queries +- Getting object metadata +- Error handling + +## Implemented Commands + +This example implements 5 key commands: + +| Command | Handler | Description | +|---------|---------|-------------| +| `CreateTableCommand` | `CreateTableHandler` | Create a new table with schema | +| `PreviewTableCommand` | `PreviewTableHandler` | Query table data with filters | +| `TableImportFromFileCommand` | `TableImportFromFileHandler` | Import data from S3/GCS/ABS | +| `ExecuteQueryCommand` | `ExecuteQueryHandler` | Execute ad-hoc SQL queries | +| `ObjectInfoCommand` | `ObjectInfoHandler` | Get object metadata | + +These commands cover the main patterns needed for other operations. + +## Usage Examples + +### Using the Client Library + +```python +from examples.client.grpc_client import StorageDriverClient + +# Connect to server +with StorageDriverClient("localhost:50051") as client: + # Create a table + client.create_table( + path=['my-project', 'my-bucket'], + table_name='users', + columns=[ + {'name': 'user_id', 'type': 'INTEGER', 'nullable': False}, + {'name': 'email', 'type': 'STRING', 'nullable': False}, + {'name': 'age', 'type': 'INTEGER', 'nullable': True}, + ], + primary_keys=['user_id'], + run_id='my-run-123' + ) + + # Import data + import_response = client.import_from_file( + path=['my-project', 'my-bucket'], + table_name='users', + file_provider="S3", + file_path={ + 'root': 'my-bucket', + 'path': 'data', + 'fileName': 'users.csv' + } + ) + print(f"Imported {import_response.importedRowsCount} rows") + + # Preview data + preview = client.preview_table( + path=['my-project', 'my-bucket'], + table_name='users', + limit=10 + ) + for row in preview.rows: + print(row) + + # Get metadata + info = client.get_object_info( + path=['my-project', 'my-bucket'], + object_name='users' + ) + table_info = info.tableInfo[0] + print(f"Table has {len(table_info.columns)} columns") +``` + +### Direct gRPC Usage + +```python +import grpc +from proto import service_pb2_grpc, common_pb2, table_pb2 + +# Connect +channel = grpc.insecure_channel('localhost:50051') +stub = service_pb2_grpc.StorageDriverServiceStub(channel) + +# Create command +cmd = table_pb2.CreateTableCommand() +cmd.path.extend(['my-project', 'my-bucket']) +cmd.tableName = 'users' + +col = cmd.columns.add() +col.name = 'user_id' +col.type = 'INTEGER' +col.nullable = False + +# Wrap in DriverRequest +request = common_pb2.DriverRequest() +request.command.Pack(cmd) +request.runtimeOptions.runId = 'my-run-123' + +# Execute +response = stub.Execute(request) + +# Check logs +for msg in response.messages: + print(f"[{msg.level}] {msg.message}") + +channel.close() +``` + +## Adding New Commands + +To add support for a new command: + +### 1. Create a Handler + +```python +# examples/handlers/my_handler.py +from examples.handlers.base_handler import BaseCommandHandler +from proto import my_command_pb2 + +class MyCommandHandler(BaseCommandHandler): + def handle(self, command, credentials, runtime_options): + # Validate inputs + self.validate_runtime_options(runtime_options) + + # Process command + result = self.storage.do_something(...) + + # Log + self.log_info("Command executed successfully") + + # Return response + response = my_command_pb2.MyCommandResponse() + # ... populate response + return response +``` + +### 2. Register in Server + +```python +# examples/grpc_server.py - in _route_command(): +elif command_type_name == 'MyCommand': + handler = MyCommandHandler(self.storage) + command = my_command_pb2.MyCommand() + command_any.Unpack(command) + return handler, command +``` + +### 3. Add Client Method (Optional) + +```python +# examples/client/grpc_client.py +def my_command(self, param1, param2, run_id=None): + """Execute MyCommand.""" + cmd = my_command_pb2.MyCommand() + cmd.param1 = param1 + cmd.param2 = param2 + + response = self._execute(cmd, run_id=run_id) + + # Unpack and return + my_response = my_command_pb2.MyCommandResponse() + response.commandResponse.Unpack(my_response) + return my_response +``` + +## Integrating Real Backends + +The mock storage backend (`storage/mock_storage.py`) should be replaced with real database connectors: + +### BigQuery Example + +```python +from google.cloud import bigquery + +class BigQueryBackend: + def __init__(self, credentials): + self.client = bigquery.Client(credentials=credentials) + + def create_table(self, path, table_name, columns, primary_keys): + dataset_id = path[0] + table_id = f"{dataset_id}.{table_name}" + + # Build schema + schema = [] + for col in columns: + field = bigquery.SchemaField( + col.name, + self._map_type(col.type), + mode="REQUIRED" if not col.nullable else "NULLABLE" + ) + schema.append(field) + + # Create table + table = bigquery.Table(table_id, schema=schema) + table = self.client.create_table(table) + + def _map_type(self, proto_type): + mapping = { + 'INTEGER': 'INTEGER', + 'STRING': 'STRING', + 'FLOAT': 'FLOAT', + 'TIMESTAMP': 'TIMESTAMP', + # ... more mappings + } + return mapping.get(proto_type, 'STRING') +``` + +### Snowflake Example + +```python +import snowflake.connector + +class SnowflakeBackend: + def __init__(self, credentials): + self.conn = snowflake.connector.connect( + user=credentials.user, + password=credentials.password, + account=credentials.account, + warehouse=credentials.warehouse, + database=credentials.database, + schema=credentials.schema + ) + + def create_table(self, path, table_name, columns, primary_keys): + # Build CREATE TABLE statement + col_defs = [] + for col in columns: + nullable = "NULL" if col.nullable else "NOT NULL" + col_def = f"{col.name} {col.type} {nullable}" + col_defs.append(col_def) + + if primary_keys: + pk_def = f"PRIMARY KEY ({', '.join(primary_keys)})" + col_defs.append(pk_def) + + sql = f"CREATE TABLE {table_name} ({', '.join(col_defs)})" + + # Execute + cursor = self.conn.cursor() + cursor.execute(sql) +``` + +## Testing + +### Unit Tests + +```bash +cd generated-py +python3 -m pytest examples/tests/test_handlers.py +``` + +### Integration Tests + +```bash +# Start server in background +python3 -m examples.grpc_server & +SERVER_PID=$! + +# Run tests +python3 -m pytest examples/tests/test_integration.py + +# Stop server +kill $SERVER_PID +``` + +## Configuration + +Server configuration can be customized via `config.py`: + +```python +from examples.config import get_config + +config = get_config( + host="0.0.0.0", + port=8080, + max_workers=20, + log_level="DEBUG", + enable_reflection=True +) +``` + +Or via command-line arguments: + +```bash +python3 -m examples.grpc_server \ + --host 0.0.0.0 \ + --port 8080 \ + --workers 20 \ + --log-level DEBUG +``` + +## Production Considerations + +This is an educational example. For production use, consider: + +### Security +- [ ] Add authentication (mTLS, JWT tokens) +- [ ] Implement authorization checks +- [ ] Encrypt credentials in transit and at rest +- [ ] Input validation and sanitization +- [ ] Rate limiting + +### Performance +- [ ] Connection pooling to backends +- [ ] Caching frequently accessed data +- [ ] Batch operations where possible +- [ ] Optimize protobuf message sizes +- [ ] Monitor and tune thread pool size + +### Reliability +- [ ] Health checks +- [ ] Graceful degradation +- [ ] Circuit breakers for backend connections +- [ ] Retry logic with exponential backoff +- [ ] Proper transaction handling + +### Observability +- [ ] Structured logging +- [ ] Metrics (Prometheus, StatsD) +- [ ] Distributed tracing (OpenTelemetry) +- [ ] Request/response logging +- [ ] Error tracking (Sentry) + +### Deployment +- [ ] Docker containerization +- [ ] Kubernetes deployment +- [ ] Load balancing +- [ ] Auto-scaling +- [ ] CI/CD pipeline + +## Troubleshooting + +### Server won't start + +Check if the port is already in use: +```bash +lsof -i :50051 +``` + +Use a different port: +```bash +python3 -m examples.grpc_server --port 8080 +``` + +### Client connection refused + +Ensure the server is running: +```bash +ps aux | grep grpc_server +``` + +Check server logs for errors. + +### Import errors + +Make sure you're in the `generated-py` directory: +```bash +cd /path/to/generated-py +python3 -m examples.grpc_server +``` + +Or set PYTHONPATH: +```bash +export PYTHONPATH="/path/to/generated-py:$PYTHONPATH" +``` + +### gRPC errors + +Enable debug logging: +```bash +export GRPC_VERBOSITY=DEBUG +export GRPC_TRACE=all +python3 -m examples.grpc_server --log-level DEBUG +``` + +## Resources + +- [gRPC Python Documentation](https://grpc.io/docs/languages/python/) +- [Protocol Buffers Python Tutorial](https://developers.google.com/protocol-buffers/docs/pythontutorial) +- [Protocol Buffers Any Type](https://developers.google.com/protocol-buffers/docs/proto3#any) +- [gRPC Best Practices](https://grpc.io/docs/guides/performance/) + +## License + +This example is part of the Keboola Storage Driver Common package. diff --git a/packages/php-storage-driver-common/generated-py/examples/__init__.py b/packages/php-storage-driver-common/generated-py/examples/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/php-storage-driver-common/generated-py/examples/client/__init__.py b/packages/php-storage-driver-common/generated-py/examples/client/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/php-storage-driver-common/generated-py/examples/client/client_examples.py b/packages/php-storage-driver-common/generated-py/examples/client/client_examples.py new file mode 100644 index 000000000..9367a4bd0 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/client/client_examples.py @@ -0,0 +1,230 @@ +""" +Example client usage for StorageDriverService. + +This module demonstrates how to use the StorageDriverClient to interact +with the gRPC server. + +Usage: + # Start the server first: + python3 examples/grpc_server.py + + # Then run the examples: + python3 examples/client/client_examples.py +""" + +import logging +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from examples.client.grpc_client import StorageDriverClient +from examples.utils import setup_logging + + +def example_create_and_query_table(): + """ + Example: Create a table, import data, and query it. + """ + print("\n" + "="*60) + print("Example: Create Table, Import Data, and Query") + print("="*60) + + with StorageDriverClient("localhost:50051") as client: + # 1. Create a table + print("\n1. Creating table 'users'...") + client.create_table( + path=['demo-project', 'demo-bucket'], + table_name='users', + columns=[ + {'name': 'user_id', 'type': 'INTEGER', 'nullable': False}, + {'name': 'email', 'type': 'STRING', 'nullable': False}, + {'name': 'age', 'type': 'INTEGER', 'nullable': True}, + {'name': 'created_at', 'type': 'TIMESTAMP', 'nullable': True}, + ], + primary_keys=['user_id'], + run_id='example-run-001' + ) + print("✓ Table created successfully") + + # 2. Import data from file + print("\n2. Importing data from file...") + import_response = client.import_from_file( + path=['demo-project', 'demo-bucket'], + table_name='users', + file_provider="S3", + file_path={ + 'root': 'my-bucket', + 'path': 'data/users', + 'fileName': 'users.csv' + }, + run_id='example-run-001' + ) + print(f"✓ Imported {import_response.importedRowsCount} rows") + print(f" Total rows in table: {import_response.tableRowsCount}") + print(f" Table size: {import_response.tableSizeBytes} bytes") + + # 3. Preview table data + print("\n3. Previewing table data...") + preview_response = client.preview_table( + path=['demo-project', 'demo-bucket'], + table_name='users', + columns=['user_id', 'email', 'age'], + limit=5, + run_id='example-run-001' + ) + print(f"✓ Retrieved {len(preview_response.rows)} rows") + print(f" Columns: {', '.join(preview_response.columns)}") + + # Display first few rows + print("\n Sample data:") + for i, row in enumerate(preview_response.rows[:3]): + values = [] + for col in row.columns: + if col.value.HasField('string_value'): + values.append(f"{col.columnName}={col.value.string_value}") + elif col.value.HasField('number_value'): + values.append(f"{col.columnName}={col.value.number_value}") + print(f" Row {i+1}: {', '.join(values)}") + + # 4. Get table info + print("\n4. Getting table metadata...") + info_response = client.get_object_info( + path=['demo-project', 'demo-bucket'], + object_name='users', + run_id='example-run-001' + ) + if info_response.tableInfo: + table_info = info_response.tableInfo[0] + print(f"✓ Table: {table_info.tableName}") + print(f" Columns: {len(table_info.columns)}") + print(f" Primary keys: {', '.join(table_info.primaryKeysNames)}") + print(f" Rows: {table_info.rowsCount}") + + +def example_execute_query(): + """ + Example: Execute ad-hoc SQL queries. + """ + print("\n" + "="*60) + print("Example: Execute SQL Query") + print("="*60) + + with StorageDriverClient("localhost:50051") as client: + print("\nExecuting query...") + query_response = client.execute_query( + sql="SELECT * FROM demo_project.demo_bucket.users WHERE age > 18 LIMIT 10", + run_id='example-run-002' + ) + print("✓ Query executed successfully") + + +def example_multiple_tables(): + """ + Example: Working with multiple tables. + """ + print("\n" + "="*60) + print("Example: Multiple Tables") + print("="*60) + + with StorageDriverClient("localhost:50051") as client: + # Create orders table + print("\n1. Creating 'orders' table...") + client.create_table( + path=['demo-project', 'demo-bucket'], + table_name='orders', + columns=[ + {'name': 'order_id', 'type': 'INTEGER', 'nullable': False}, + {'name': 'user_id', 'type': 'INTEGER', 'nullable': False}, + {'name': 'total', 'type': 'DECIMAL', 'nullable': False}, + {'name': 'status', 'type': 'STRING', 'nullable': False}, + ], + primary_keys=['order_id'], + run_id='example-run-003' + ) + print("✓ Orders table created") + + # Import data into orders + print("\n2. Importing orders data...") + import_response = client.import_from_file( + path=['demo-project', 'demo-bucket'], + table_name='orders', + file_provider="S3", + file_path={ + 'root': 'my-bucket', + 'path': 'data/orders', + 'fileName': 'orders.csv' + }, + run_id='example-run-003' + ) + print(f"✓ Imported {import_response.importedRowsCount} rows into orders") + + +def example_error_handling(): + """ + Example: Error handling. + """ + print("\n" + "="*60) + print("Example: Error Handling") + print("="*60) + + with StorageDriverClient("localhost:50051") as client: + # Try to preview a non-existent table + print("\n1. Attempting to preview non-existent table...") + try: + preview_response = client.preview_table( + path=['demo-project', 'demo-bucket'], + table_name='non_existent_table', + limit=10 + ) + except Exception as e: + print(f"✓ Caught expected error: {e}") + + # Try to create a table with invalid name + print("\n2. Attempting to create table with invalid parameters...") + try: + client.create_table( + path=['demo-project', 'demo-bucket'], + table_name='', # Invalid: empty name + columns=[ + {'name': 'col1', 'type': 'STRING', 'nullable': False} + ] + ) + except Exception as e: + print(f"✓ Caught expected error: {e}") + + +def main(): + """ + Run all examples. + """ + # Set up logging + setup_logging(logging.INFO) + + print("\n" + "="*60) + print("StorageDriverService gRPC Client Examples") + print("="*60) + print("\nMake sure the gRPC server is running:") + print(" python3 examples/grpc_server.py") + print("\nPress Enter to continue...") + input() + + try: + # Run examples + example_create_and_query_table() + example_execute_query() + example_multiple_tables() + example_error_handling() + + print("\n" + "="*60) + print("All examples completed successfully!") + print("="*60 + "\n") + + except Exception as e: + print(f"\n❌ Error running examples: {e}") + print("\nMake sure the gRPC server is running:") + print(" python3 examples/grpc_server.py") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/packages/php-storage-driver-common/generated-py/examples/client/grpc_client.py b/packages/php-storage-driver-common/generated-py/examples/client/grpc_client.py new file mode 100644 index 000000000..4cd2a87db --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/client/grpc_client.py @@ -0,0 +1,352 @@ +""" +gRPC Client for StorageDriverService. + +This module provides a convenient client wrapper for interacting with +the StorageDriverService gRPC server. + +Usage: + from examples.client.grpc_client import StorageDriverClient + + client = StorageDriverClient("localhost:50051") + response = client.create_table(...) + client.close() + +Or use as context manager: + with StorageDriverClient("localhost:50051") as client: + response = client.create_table(...) +""" + +import logging +from typing import List, Optional + +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +import grpc +from proto import service_pb2_grpc, common_pb2, table_pb2, executeQuery_pb2, info_pb2 + + +logger = logging.getLogger(__name__) + + +class StorageDriverClient: + """ + Client for StorageDriverService gRPC API. + + This class provides convenient methods for calling the StorageDriverService + while handling the protobuf wrapping/unwrapping patterns. + + Example: + >>> client = StorageDriverClient("localhost:50051") + >>> client.create_table(['project'], 'users', [...]) + >>> client.close() + """ + + def __init__(self, address: str, timeout: int = 30): + """ + Initialize the client. + + Args: + address: Server address (e.g., "localhost:50051") + timeout: Default timeout for requests in seconds + """ + self.address = address + self.timeout = timeout + self.channel = grpc.insecure_channel(address) + self.stub = service_pb2_grpc.StorageDriverServiceStub(self.channel) + logger.info(f"Connected to StorageDriverService at {address}") + + def close(self): + """Close the gRPC channel.""" + if self.channel: + self.channel.close() + logger.info("Channel closed") + + def __enter__(self): + """Context manager entry.""" + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Context manager exit.""" + self.close() + + def _execute( + self, + command, + run_id: Optional[str] = None, + query_tags: Optional[dict] = None + ) -> common_pb2.DriverResponse: + """ + Execute a command. + + Args: + command: Command message + run_id: Optional run ID + query_tags: Optional query tags + + Returns: + DriverResponse + + Raises: + grpc.RpcError: On RPC errors + """ + # Create DriverRequest + request = common_pb2.DriverRequest() + request.command.Pack(command) + + # Set runtime options + if run_id: + request.runtimeOptions.runId = run_id + if query_tags: + for key, value in query_tags.items(): + request.runtimeOptions.queryTags[key] = value + + # Execute request + try: + response = self.stub.Execute(request, timeout=self.timeout) + + # Log any messages from server + for msg in response.messages: + level = msg.level + if level <= common_pb2.LogMessage.Level.Error: + logger.error(f"Server: {msg.message}") + elif level == common_pb2.LogMessage.Level.Warning: + logger.warning(f"Server: {msg.message}") + else: + logger.info(f"Server: {msg.message}") + + return response + + except grpc.RpcError as e: + logger.error(f"RPC failed: {e.code()} - {e.details()}") + raise + + def create_table( + self, + path: List[str], + table_name: str, + columns: List[dict], + primary_keys: Optional[List[str]] = None, + run_id: Optional[str] = None + ) -> None: + """ + Create a table. + + Args: + path: Table path components (e.g., ['project', 'bucket']) + table_name: Table name + columns: List of column definitions, each with keys: 'name', 'type', 'nullable' + primary_keys: Optional list of primary key column names + run_id: Optional run ID + + Example: + >>> client.create_table( + ... path=['my-project', 'my-bucket'], + ... table_name='users', + ... columns=[ + ... {'name': 'user_id', 'type': 'INTEGER', 'nullable': False}, + ... {'name': 'email', 'type': 'STRING', 'nullable': False}, + ... ], + ... primary_keys=['user_id'] + ... ) + """ + cmd = table_pb2.CreateTableCommand() + cmd.path.extend(path) + cmd.tableName = table_name + + # Add columns + for col_def in columns: + col = cmd.columns.add() + col.name = col_def['name'] + col.type = col_def['type'] + col.nullable = col_def.get('nullable', True) + if 'length' in col_def: + col.length = col_def['length'] + if 'default' in col_def: + col.default = col_def['default'] + + # Add primary keys + if primary_keys: + cmd.primaryKeysNames.extend(primary_keys) + + self._execute(cmd, run_id=run_id) + logger.info(f"Table {'.'.join(path + [table_name])} created") + + def preview_table( + self, + path: List[str], + table_name: str, + columns: Optional[List[str]] = None, + limit: Optional[int] = None, + run_id: Optional[str] = None + ) -> table_pb2.PreviewTableResponse: + """ + Preview table data. + + Args: + path: Table path components + table_name: Table name + columns: Optional list of columns to return + limit: Optional limit on number of rows + run_id: Optional run ID + + Returns: + PreviewTableResponse with table data + + Example: + >>> response = client.preview_table( + ... path=['my-project', 'my-bucket'], + ... table_name='users', + ... limit=10 + ... ) + >>> print(f"Columns: {response.columns}") + >>> for row in response.rows: + ... print(row) + """ + cmd = table_pb2.PreviewTableCommand() + cmd.path.extend(path) + cmd.tableName = table_name + + if columns: + cmd.columns.extend(columns) + + if limit: + cmd.filters.limit = limit + + response = self._execute(cmd, run_id=run_id) + + # Unpack response + preview_response = table_pb2.PreviewTableResponse() + response.commandResponse.Unpack(preview_response) + + logger.info(f"Preview returned {len(preview_response.rows)} rows") + return preview_response + + def import_from_file( + self, + path: List[str], + table_name: str, + file_provider: str = "S3", + file_path: dict = None, + run_id: Optional[str] = None + ) -> table_pb2.TableImportResponse: + """ + Import data from a file into a table. + + Args: + path: Destination table path components + table_name: Destination table name + file_provider: File provider ("S3", "GCS", "ABS") + file_path: File path dict with keys: 'root', 'path', 'fileName' + run_id: Optional run ID + + Returns: + TableImportResponse with import statistics + + Example: + >>> response = client.import_from_file( + ... path=['my-project', 'my-bucket'], + ... table_name='users', + ... file_provider="S3", + ... file_path={'root': 'my-bucket', 'path': 'data', 'fileName': 'users.csv'} + ... ) + >>> print(f"Imported {response.importedRowsCount} rows") + """ + cmd = table_pb2.TableImportFromFileCommand() + + # Set destination + cmd.destination.path.extend(path) + cmd.destination.tableName = table_name + + # Set file provider + if file_provider == "S3": + cmd.fileProvider = table_pb2.ImportExportShared.FileProvider.S3 + elif file_provider == "GCS": + cmd.fileProvider = table_pb2.ImportExportShared.FileProvider.GCS + elif file_provider == "ABS": + cmd.fileProvider = table_pb2.ImportExportShared.FileProvider.ABS + + # Set file format (CSV for now) + cmd.fileFormat = table_pb2.ImportExportShared.FileFormat.CSV + + # Set file path + if file_path: + cmd.filePath.root = file_path.get('root', '') + cmd.filePath.path = file_path.get('path', '') + cmd.filePath.fileName = file_path.get('fileName', '') + + response = self._execute(cmd, run_id=run_id) + + # Unpack response + import_response = table_pb2.TableImportResponse() + response.commandResponse.Unpack(import_response) + + logger.info(f"Import completed: {import_response.importedRowsCount} rows") + return import_response + + def execute_query( + self, + sql: str, + run_id: Optional[str] = None + ) -> executeQuery_pb2.ExecuteQueryResponse: + """ + Execute a SQL query. + + Args: + sql: SQL query string + run_id: Optional run ID + + Returns: + ExecuteQueryResponse with query results + + Example: + >>> response = client.execute_query("SELECT * FROM users LIMIT 10") + """ + cmd = executeQuery_pb2.ExecuteQueryCommand() + cmd.sql = sql + + response = self._execute(cmd, run_id=run_id) + + # Unpack response + query_response = executeQuery_pb2.ExecuteQueryResponse() + response.commandResponse.Unpack(query_response) + + logger.info("Query executed") + return query_response + + def get_object_info( + self, + path: List[str], + object_name: str, + run_id: Optional[str] = None + ) -> info_pb2.ObjectInfoResponse: + """ + Get object metadata. + + Args: + path: Object path components + object_name: Object name + run_id: Optional run ID + + Returns: + ObjectInfoResponse with object metadata + + Example: + >>> response = client.get_object_info(['my-project', 'my-bucket'], 'users') + >>> table_info = response.tableInfo[0] + >>> print(f"Table: {table_info.tableName}") + >>> print(f"Columns: {len(table_info.columns)}") + """ + cmd = info_pb2.ObjectInfoCommand() + cmd.path.extend(path) + cmd.objectName = object_name + + response = self._execute(cmd, run_id=run_id) + + # Unpack response + info_response = info_pb2.ObjectInfoResponse() + response.commandResponse.Unpack(info_response) + + logger.info(f"Retrieved info for {object_name}") + return info_response diff --git a/packages/php-storage-driver-common/generated-py/examples/config.py b/packages/php-storage-driver-common/generated-py/examples/config.py new file mode 100644 index 000000000..99dda7710 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/config.py @@ -0,0 +1,72 @@ +""" +Configuration for the gRPC server example. + +This module provides configuration settings for the StorageDriverService gRPC server. +""" + +import logging +from typing import Dict, Any + + +class ServerConfig: + """ + Configuration for the gRPC server. + + Attributes: + host: Server host address + port: Server port + max_workers: Maximum number of worker threads for handling requests + log_level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) + enable_reflection: Enable gRPC server reflection for debugging + """ + + def __init__( + self, + host: str = "localhost", + port: int = 50051, + max_workers: int = 10, + log_level: str = "INFO", + enable_reflection: bool = True + ): + self.host = host + self.port = port + self.max_workers = max_workers + self.log_level = getattr(logging, log_level.upper()) + self.enable_reflection = enable_reflection + + @property + def address(self) -> str: + """Returns the full server address.""" + return f"{self.host}:{self.port}" + + def to_dict(self) -> Dict[str, Any]: + """Convert configuration to dictionary.""" + return { + "host": self.host, + "port": self.port, + "max_workers": self.max_workers, + "log_level": logging.getLevelName(self.log_level), + "enable_reflection": self.enable_reflection, + } + + +# Default configuration +DEFAULT_CONFIG = ServerConfig() + + +def get_config(**kwargs) -> ServerConfig: + """ + Get server configuration with optional overrides. + + Args: + **kwargs: Configuration overrides + + Returns: + ServerConfig instance + + Example: + >>> config = get_config(port=8080, log_level="DEBUG") + >>> print(config.address) + localhost:8080 + """ + return ServerConfig(**kwargs) diff --git a/packages/php-storage-driver-common/generated-py/examples/grpc_server.py b/packages/php-storage-driver-common/generated-py/examples/grpc_server.py new file mode 100644 index 000000000..a358644d6 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/grpc_server.py @@ -0,0 +1,336 @@ +""" +gRPC Server implementation for StorageDriverService. + +This module implements the gRPC server that handles Storage Driver commands. +It routes incoming requests to appropriate handlers based on command type. + +Usage: + python3 grpc_server.py + +Or: + from examples.grpc_server import serve + serve(port=50051) +""" + +import logging +import signal +import sys +from concurrent import futures +from pathlib import Path + +# Add generated proto modules to path +sys.path.insert(0, str(Path(__file__).parent.parent)) + +import grpc +from proto import service_pb2_grpc, common_pb2, table_pb2, executeQuery_pb2, info_pb2 +from google.protobuf.message import Message + +from examples.config import get_config +from examples.utils import setup_logging, get_type_name, pack_message +from examples.storage.mock_storage import MockStorageBackend +from examples.handlers.table_handler import ( + CreateTableHandler, + PreviewTableHandler, + TableImportFromFileHandler +) +from examples.handlers.query_handler import ExecuteQueryHandler +from examples.handlers.info_handler import ObjectInfoHandler + + +logger = logging.getLogger(__name__) + + +class StorageDriverServicer(service_pb2_grpc.StorageDriverServiceServicer): + """ + Implementation of the StorageDriverService. + + This class implements the gRPC service defined in service.proto. + It handles the Execute() RPC method by: + 1. Unpacking the command from DriverRequest + 2. Routing to the appropriate handler + 3. Wrapping the response in DriverResponse + 4. Including log messages for the client + """ + + def __init__(self, storage: MockStorageBackend): + """ + Initialize the servicer. + + Args: + storage: Mock storage backend instance + """ + self.storage = storage + logger.info("StorageDriverServicer initialized") + + def Execute( + self, + request: common_pb2.DriverRequest, + context: grpc.ServicerContext + ) -> common_pb2.DriverResponse: + """ + Execute a storage driver command. + + This is the main RPC method that handles all commands. + It uses the google.protobuf.Any wrapper pattern to support + different command types through a single interface. + + Args: + request: DriverRequest containing the command + context: gRPC context + + Returns: + DriverResponse with command result and log messages + + Raises: + grpc.RpcError: On validation or execution errors + """ + try: + # Extract command type from Any field + command_type_name = get_type_name(request.command) + logger.info(f"Received command: {command_type_name}") + + # Log runtime info + if request.runtimeOptions and request.runtimeOptions.runId: + logger.debug(f"RunID: {request.runtimeOptions.runId}") + + # Route command to appropriate handler + handler, command_msg = self._route_command(request.command, command_type_name) + + if handler is None: + error_msg = f"Unsupported command type: {command_type_name}" + logger.error(error_msg) + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details(error_msg) + return self._create_error_response(error_msg) + + # Execute handler + try: + response_msg = handler.handle( + command_msg, + None, # TODO: Unpack credentials from request.credentials + request.runtimeOptions + ) + + # Get log messages from handler + log_messages = handler.get_log_messages() + + # Wrap response + return self._wrap_response(response_msg, log_messages) + + except ValueError as e: + # Invalid parameters + logger.error(f"Invalid parameters: {e}") + context.set_code(grpc.StatusCode.INVALID_ARGUMENT) + context.set_details(str(e)) + return self._create_error_response(str(e), handler.get_log_messages()) + + except KeyError as e: + # Resource not found + logger.error(f"Resource not found: {e}") + context.set_code(grpc.StatusCode.NOT_FOUND) + context.set_details(str(e)) + return self._create_error_response(str(e), handler.get_log_messages()) + + except Exception as e: + # Internal error + logger.exception(f"Internal error processing {command_type_name}") + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(f"Internal error: {str(e)}") + return self._create_error_response(f"Internal error: {str(e)}") + + except Exception as e: + # Error during routing or unpacking + logger.exception("Error in Execute()") + context.set_code(grpc.StatusCode.INTERNAL) + context.set_details(str(e)) + return self._create_error_response(str(e)) + + def _route_command( + self, + command_any, + command_type_name: str + ) -> tuple: + """ + Route command to appropriate handler. + + Args: + command_any: google.protobuf.Any containing the command + command_type_name: Name of the command type + + Returns: + Tuple of (handler_instance, unpacked_command) or (None, None) + """ + # Table commands + if command_type_name == 'CreateTableCommand': + handler = CreateTableHandler(self.storage) + command = table_pb2.CreateTableCommand() + command_any.Unpack(command) + return handler, command + + elif command_type_name == 'PreviewTableCommand': + handler = PreviewTableHandler(self.storage) + command = table_pb2.PreviewTableCommand() + command_any.Unpack(command) + return handler, command + + elif command_type_name == 'TableImportFromFileCommand': + handler = TableImportFromFileHandler(self.storage) + command = table_pb2.TableImportFromFileCommand() + command_any.Unpack(command) + return handler, command + + # Query commands + elif command_type_name == 'ExecuteQueryCommand': + handler = ExecuteQueryHandler(self.storage) + command = executeQuery_pb2.ExecuteQueryCommand() + command_any.Unpack(command) + return handler, command + + # Info commands + elif command_type_name == 'ObjectInfoCommand': + handler = ObjectInfoHandler(self.storage) + command = info_pb2.ObjectInfoCommand() + command_any.Unpack(command) + return handler, command + + # Add more command types here as needed + # elif command_type_name == 'DropTableCommand': + # ... + + return None, None + + def _wrap_response( + self, + command_response: Message | None, + log_messages: list + ) -> common_pb2.DriverResponse: + """ + Wrap command response in DriverResponse. + + Args: + command_response: The command-specific response message (or None) + log_messages: List of LogMessage instances + + Returns: + DriverResponse with wrapped response and log messages + """ + driver_response = common_pb2.DriverResponse() + + # Pack command response if present + if command_response is not None: + driver_response.commandResponse.Pack(command_response) + + # Add log messages + driver_response.messages.extend(log_messages) + + return driver_response + + def _create_error_response( + self, + error_message: str, + log_messages: list | None = None + ) -> common_pb2.DriverResponse: + """ + Create an error response. + + Args: + error_message: Error message + log_messages: Optional existing log messages + + Returns: + DriverResponse with error log message + """ + driver_response = common_pb2.DriverResponse() + + # Add existing log messages + if log_messages: + driver_response.messages.extend(log_messages) + + # Add error log message + error_log = common_pb2.LogMessage() + error_log.level = common_pb2.LogMessage.Level.Error + error_log.message = error_message + driver_response.messages.append(error_log) + + return driver_response + + +def serve(host: str = "localhost", port: int = 50051, max_workers: int = 10): + """ + Start the gRPC server. + + Args: + host: Server host + port: Server port + max_workers: Maximum number of worker threads + + Example: + >>> serve(port=8080, max_workers=20) + """ + # Set up logging + setup_logging(logging.INFO) + + # Create storage backend + storage = MockStorageBackend() + + # Create gRPC server + server = grpc.server(futures.ThreadPoolExecutor(max_workers=max_workers)) + + # Register servicer + service_pb2_grpc.add_StorageDriverServiceServicer_to_server( + StorageDriverServicer(storage), + server + ) + + # Bind to address + address = f"{host}:{port}" + server.add_insecure_port(address) + + # Start server + server.start() + logger.info(f"StorageDriverService gRPC server started on {address}") + logger.info(f"Ready to accept connections (max workers: {max_workers})") + + # Handle graceful shutdown + def handle_shutdown(signum, frame): + logger.info("Shutting down server...") + server.stop(grace=5) + logger.info("Server stopped") + sys.exit(0) + + signal.signal(signal.SIGINT, handle_shutdown) + signal.signal(signal.SIGTERM, handle_shutdown) + + # Wait for termination + try: + server.wait_for_termination() + except KeyboardInterrupt: + logger.info("Keyboard interrupt received, shutting down...") + server.stop(grace=5) + + +if __name__ == "__main__": + """ + Run the server from command line. + + Usage: + python3 grpc_server.py + python3 grpc_server.py --port 8080 + """ + import argparse + + parser = argparse.ArgumentParser(description="StorageDriver gRPC Server") + parser.add_argument("--host", default="localhost", help="Server host (default: localhost)") + parser.add_argument("--port", type=int, default=50051, help="Server port (default: 50051)") + parser.add_argument("--workers", type=int, default=10, help="Max worker threads (default: 10)") + parser.add_argument("--log-level", default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR"], + help="Logging level (default: INFO)") + + args = parser.parse_args() + + # Set up logging with specified level + log_level = getattr(logging, args.log_level.upper()) + setup_logging(log_level) + + # Start server + serve(host=args.host, port=args.port, max_workers=args.workers) diff --git a/packages/php-storage-driver-common/generated-py/examples/handlers/__init__.py b/packages/php-storage-driver-common/generated-py/examples/handlers/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/php-storage-driver-common/generated-py/examples/handlers/base_handler.py b/packages/php-storage-driver-common/generated-py/examples/handlers/base_handler.py new file mode 100644 index 000000000..db874dea7 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/handlers/base_handler.py @@ -0,0 +1,270 @@ +""" +Base handler for command processing. + +This module provides the abstract base class for all command handlers. +Handlers are responsible for processing specific command types and returning responses. +""" + +import logging +from abc import ABC, abstractmethod +from typing import Optional +from google.protobuf.message import Message + +# Add generated proto modules to path +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from proto import common_pb2 +from examples.utils import LogMessageCollector +from examples.storage.mock_storage import MockStorageBackend + + +logger = logging.getLogger(__name__) + + +class BaseCommandHandler(ABC): + """ + Abstract base class for command handlers. + + This class provides common functionality for all command handlers: + - Access to storage backend + - Log message collection + - Error handling patterns + - Response wrapping + + Subclasses must implement the handle() method to process specific command types. + + Example: + >>> class MyHandler(BaseCommandHandler): + ... def handle(self, command, credentials, runtime_options): + ... self.log_collector.info("Processing command") + ... # Process command + ... return my_response + """ + + def __init__(self, storage: MockStorageBackend): + """ + Initialize the handler. + + Args: + storage: Storage backend instance + """ + self.storage = storage + self.log_collector = LogMessageCollector() + self.logger = logging.getLogger(self.__class__.__name__) + + @abstractmethod + def handle( + self, + command: Message, + credentials: Optional[Message], + runtime_options: common_pb2.RuntimeOptions + ) -> Message: + """ + Handle the command and return a response. + + This method must be implemented by subclasses to handle specific command types. + + Args: + command: The command message to process + credentials: Optional credentials for backend access + runtime_options: Runtime options (runId, queryTags, etc.) + + Returns: + Response message specific to the command type + + Raises: + ValueError: For invalid command parameters + KeyError: For missing resources (tables, buckets) + Exception: For other errors + """ + pass + + def get_log_messages(self) -> list: + """ + Get all collected log messages. + + Returns: + List of LogMessage instances + """ + return self.log_collector.get_messages() + + def clear_logs(self) -> None: + """Clear all collected log messages.""" + self.log_collector.clear() + + def log_info(self, message: str) -> None: + """ + Log an informational message. + + The message is added to both: + 1. Internal Python logger (for debugging) + 2. Log collector (for inclusion in DriverResponse) + + Args: + message: Log message + """ + self.logger.info(message) + self.log_collector.info(message) + + def log_warning(self, message: str) -> None: + """ + Log a warning message. + + Args: + message: Log message + """ + self.logger.warning(message) + self.log_collector.warning(message) + + def log_error(self, message: str) -> None: + """ + Log an error message. + + Args: + message: Log message + """ + self.logger.error(message) + self.log_collector.error(message) + + def log_debug(self, message: str) -> None: + """ + Log a debug message. + + Args: + message: Log message + """ + self.logger.debug(message) + self.log_collector.debug(message) + + def validate_runtime_options(self, runtime_options: common_pb2.RuntimeOptions) -> None: + """ + Validate runtime options. + + Args: + runtime_options: Runtime options to validate + + Raises: + ValueError: If validation fails + """ + if runtime_options and runtime_options.runId: + self.log_debug(f"Processing request with runId: {runtime_options.runId}") + + # Log query tags if present + if runtime_options.queryTags: + tags = dict(runtime_options.queryTags) + self.log_debug(f"Query tags: {tags}") + + def handle_error(self, error: Exception) -> None: + """ + Handle an error during command processing. + + This method logs the error and adds it to the log collector. + The error will be propagated up to be handled by the gRPC server. + + Args: + error: The exception that occurred + """ + error_msg = f"Error processing command: {str(error)}" + self.log_error(error_msg) + self.logger.exception("Exception details:") + + def create_empty_response(self, response_class): + """ + Create an empty response of the specified type. + + Args: + response_class: The response message class + + Returns: + Empty response instance + """ + return response_class() + + +class TableCommandHandlerMixin: + """ + Mixin for handlers that deal with table operations. + + Provides common validation and helper methods for table-related commands. + """ + + def validate_table_path(self, path: list, table_name: str) -> None: + """ + Validate table path components. + + Args: + path: List of path components + table_name: Table name + + Raises: + ValueError: If validation fails + """ + if not path: + raise ValueError("Table path cannot be empty") + + if not table_name or not table_name.strip(): + raise ValueError("Table name cannot be empty") + + # Basic name validation + if not all(c.isalnum() or c in ('_', '-') for c in table_name): + raise ValueError(f"Invalid table name: {table_name}") + + def format_table_path(self, path: list, table_name: str) -> str: + """ + Format table path for logging/display. + + Args: + path: List of path components + table_name: Table name + + Returns: + Formatted path string (e.g., "project.bucket.table") + """ + return '.'.join(list(path) + [table_name]) + + def validate_columns(self, columns: list) -> None: + """ + Validate column definitions. + + Args: + columns: List of TableColumnShared messages + + Raises: + ValueError: If validation fails + """ + if not columns: + raise ValueError("Table must have at least one column") + + column_names = set() + for col in columns: + if not col.name: + raise ValueError("Column name cannot be empty") + + if col.name in column_names: + raise ValueError(f"Duplicate column name: {col.name}") + + column_names.add(col.name) + + if not col.type: + raise ValueError(f"Column {col.name} must have a type") + + def validate_primary_keys(self, columns: list, primary_keys: list) -> None: + """ + Validate primary key definitions. + + Args: + columns: List of column definitions + primary_keys: List of primary key column names + + Raises: + ValueError: If validation fails + """ + if not primary_keys: + return + + column_names = {col.name for col in columns} + for pk in primary_keys: + if pk not in column_names: + raise ValueError(f"Primary key '{pk}' not found in table columns") diff --git a/packages/php-storage-driver-common/generated-py/examples/handlers/info_handler.py b/packages/php-storage-driver-common/generated-py/examples/handlers/info_handler.py new file mode 100644 index 000000000..7c3516062 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/handlers/info_handler.py @@ -0,0 +1,105 @@ +""" +Information query handler. + +This module implements the handler for ObjectInfoCommand. +""" + +import logging + +# Add generated proto modules to path +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from proto import info_pb2, common_pb2 +from examples.handlers.base_handler import BaseCommandHandler +from examples.storage.mock_storage import MockStorageBackend + + +logger = logging.getLogger(__name__) + + +class ObjectInfoHandler(BaseCommandHandler): + """ + Handler for ObjectInfoCommand. + + Returns metadata about database objects (tables, schemas, databases). + + Example command: + ObjectInfoCommand( + path=['project-123', 'bucket-456'], + objectName='users' + ) + """ + + def __init__(self, storage: MockStorageBackend): + super().__init__(storage) + + def handle( + self, + command: info_pb2.ObjectInfoCommand, + credentials, + runtime_options: common_pb2.RuntimeOptions + ) -> info_pb2.ObjectInfoResponse: + """ + Handle ObjectInfoCommand. + + Args: + command: ObjectInfoCommand message + credentials: Backend credentials (unused in mock) + runtime_options: Runtime options + + Returns: + ObjectInfoResponse with object metadata + + Raises: + KeyError: If object doesn't exist + """ + self.validate_runtime_options(runtime_options) + + path = list(command.path) + object_name = command.objectName + + if not object_name: + raise ValueError("Object name cannot be empty") + + self.log_info(f"Getting info for object: {'.'.join(path + [object_name])}") + + # For this mock, we assume it's a table query + try: + if not self.storage.table_exists(path, object_name): + raise KeyError(f"Object not found: {object_name}") + + table_info = self.storage.get_table_info(path, object_name) + + # Build response + response = info_pb2.ObjectInfoResponse() + + # Add table info + table_info_msg = response.tableInfo.add() + table_info_msg.tableName = table_info['name'] + table_info_msg.path.extend(path) + + # Add columns + for col in table_info['columns']: + col_msg = table_info_msg.columns.add() + col_msg.name = col['name'] + col_msg.type = col['type'] + col_msg.nullable = col['nullable'] + + # Add primary keys + table_info_msg.primaryKeysNames.extend(table_info['primary_keys']) + + # Add row count + table_info_msg.rowsCount = str(table_info['row_count']) + + self.log_info(f"Found table {object_name} with {len(table_info['columns'])} columns") + + return response + + except KeyError as e: + self.handle_error(e) + raise + except Exception as e: + self.handle_error(e) + raise diff --git a/packages/php-storage-driver-common/generated-py/examples/handlers/query_handler.py b/packages/php-storage-driver-common/generated-py/examples/handlers/query_handler.py new file mode 100644 index 000000000..6047f2cba --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/handlers/query_handler.py @@ -0,0 +1,88 @@ +""" +Query execution handler. + +This module implements the handler for ExecuteQueryCommand. +""" + +import logging + +# Add generated proto modules to path +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from proto import executeQuery_pb2, common_pb2 +from examples.handlers.base_handler import BaseCommandHandler +from examples.storage.mock_storage import MockStorageBackend + + +logger = logging.getLogger(__name__) + + +class ExecuteQueryHandler(BaseCommandHandler): + """ + Handler for ExecuteQueryCommand. + + Executes ad-hoc SQL queries against the storage backend. + This mock implementation demonstrates the pattern but doesn't execute real SQL. + + Example command: + ExecuteQueryCommand( + sql="SELECT * FROM users WHERE age > 18" + ) + """ + + def __init__(self, storage: MockStorageBackend): + super().__init__(storage) + + def handle( + self, + command: executeQuery_pb2.ExecuteQueryCommand, + credentials, + runtime_options: common_pb2.RuntimeOptions + ) -> executeQuery_pb2.ExecuteQueryResponse: + """ + Handle ExecuteQueryCommand. + + Args: + command: ExecuteQueryCommand message + credentials: Backend credentials (unused in mock) + runtime_options: Runtime options + + Returns: + ExecuteQueryResponse with query results + + Raises: + ValueError: If query is invalid + """ + self.validate_runtime_options(runtime_options) + + sql = command.sql.strip() + + if not sql: + raise ValueError("SQL query cannot be empty") + + self.log_info(f"Executing query: {sql[:100]}{'...' if len(sql) > 100 else ''}") + + # TODO: In a real implementation, this would: + # 1. Parse and validate the SQL query + # 2. Execute it against the backend database + # 3. Return actual results + + # For this mock, we'll return an empty result set + try: + results = self.storage.execute_query(sql) + + self.log_info(f"Query executed successfully, returned {len(results)} rows") + + # Build response + response = executeQuery_pb2.ExecuteQueryResponse() + + # Mock: set empty columns and rows + # In a real implementation, these would come from actual query results + + return response + + except Exception as e: + self.handle_error(e) + raise diff --git a/packages/php-storage-driver-common/generated-py/examples/handlers/table_handler.py b/packages/php-storage-driver-common/generated-py/examples/handlers/table_handler.py new file mode 100644 index 000000000..db1888dcf --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/handlers/table_handler.py @@ -0,0 +1,373 @@ +""" +Table operation handlers. + +This module implements handlers for table-related commands: +- CreateTableCommand +- PreviewTableCommand +- TableImportFromFileCommand +""" + +import logging +from typing import List, Dict, Any + +# Add generated proto modules to path +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from proto import table_pb2, common_pb2 +from google.protobuf import struct_pb2 +from examples.handlers.base_handler import BaseCommandHandler, TableCommandHandlerMixin +from examples.storage.mock_storage import MockStorageBackend, ColumnSchema + + +logger = logging.getLogger(__name__) + + +class CreateTableHandler(BaseCommandHandler, TableCommandHandlerMixin): + """ + Handler for CreateTableCommand. + + Creates a new table with the specified schema in the storage backend. + + Example command: + CreateTableCommand( + path=['project-123', 'bucket-456'], + tableName='users', + columns=[...], + primaryKeysNames=['user_id'] + ) + """ + + def __init__(self, storage: MockStorageBackend): + super().__init__(storage) + + def handle( + self, + command: table_pb2.CreateTableCommand, + credentials, + runtime_options: common_pb2.RuntimeOptions + ) -> None: + """ + Handle CreateTableCommand. + + Args: + command: CreateTableCommand message + credentials: Backend credentials (unused in mock) + runtime_options: Runtime options + + Returns: + None (CreateTableCommand has no response type) + + Raises: + ValueError: If table parameters are invalid + """ + self.validate_runtime_options(runtime_options) + + # Extract table details + path = list(command.path) + table_name = command.tableName + columns = command.columns + primary_keys = list(command.primaryKeysNames) + + # Validate inputs + self.validate_table_path(path, table_name) + self.validate_columns(columns) + self.validate_primary_keys(columns, primary_keys) + + table_path_str = self.format_table_path(path, table_name) + + # Check if table already exists + if self.storage.table_exists(path, table_name): + raise ValueError(f"Table {table_path_str} already exists") + + # Convert protobuf columns to storage schema + column_schemas = [] + for col in columns: + col_schema = ColumnSchema( + name=col.name, + type=col.type, + length=col.length if col.length else "", + nullable=col.nullable, + default=col.default if col.default else None + ) + column_schemas.append(col_schema) + + # Create table in storage + try: + self.storage.create_table( + path=path, + table_name=table_name, + columns=column_schemas, + primary_keys=primary_keys if primary_keys else None + ) + + self.log_info( + f"Table {table_path_str} created successfully with " + f"{len(columns)} columns" + ) + + if primary_keys: + self.log_info(f"Primary keys: {', '.join(primary_keys)}") + + except Exception as e: + self.handle_error(e) + raise + + +class PreviewTableHandler(BaseCommandHandler, TableCommandHandlerMixin): + """ + Handler for PreviewTableCommand. + + Returns a preview of table data with optional filtering and ordering. + + Example command: + PreviewTableCommand( + path=['project-123', 'bucket-456'], + tableName='users', + columns=['user_id', 'email'], + filters=ExportFilters(limit=10) + ) + """ + + def __init__(self, storage: MockStorageBackend): + super().__init__(storage) + + def handle( + self, + command: table_pb2.PreviewTableCommand, + credentials, + runtime_options: common_pb2.RuntimeOptions + ) -> table_pb2.PreviewTableResponse: + """ + Handle PreviewTableCommand. + + Args: + command: PreviewTableCommand message + credentials: Backend credentials (unused in mock) + runtime_options: Runtime options + + Returns: + PreviewTableResponse with table data + + Raises: + KeyError: If table doesn't exist + ValueError: If parameters are invalid + """ + self.validate_runtime_options(runtime_options) + + # Extract query parameters + path = list(command.path) + table_name = command.tableName + columns = list(command.columns) if command.columns else None + limit = None + + # Extract limit from filters if present + if command.HasField('filters') and command.filters.limit > 0: + limit = command.filters.limit + + self.validate_table_path(path, table_name) + table_path_str = self.format_table_path(path, table_name) + + # Query table data + try: + rows, schema = self.storage.query_table( + path=path, + table_name=table_name, + columns=columns, + limit=limit + ) + + self.log_info( + f"Preview table {table_path_str}: " + f"returning {len(rows)} rows" + ) + + # Build response + response = table_pb2.PreviewTableResponse() + + # Add column names + if columns: + response.columns.extend(columns) + else: + # Use all columns from schema + response.columns.extend([col.name for col in schema.columns]) + + # Add rows + for row_data in rows: + row = response.rows.add() + for col_name in response.columns: + col_value = row.columns.add() + col_value.columnName = col_name + + # Convert value to protobuf Value + value = row_data.get(col_name) + if value is not None: + if isinstance(value, bool): + col_value.value.bool_value = value + elif isinstance(value, int): + col_value.value.number_value = float(value) + elif isinstance(value, float): + col_value.value.number_value = value + elif isinstance(value, str): + col_value.value.string_value = value + else: + col_value.value.string_value = str(value) + else: + col_value.value.null_value = struct_pb2.NULL_VALUE + + col_value.isTruncated = False + + return response + + except KeyError as e: + self.handle_error(e) + raise KeyError(f"Table {table_path_str} not found") + except Exception as e: + self.handle_error(e) + raise + + +class TableImportFromFileHandler(BaseCommandHandler, TableCommandHandlerMixin): + """ + Handler for TableImportFromFileCommand. + + Imports data from a file (S3, GCS, ABS) into a table. + This is a mock implementation that generates sample data instead of + actually reading from cloud storage. + + Example command: + TableImportFromFileCommand( + fileProvider=FileProvider.S3, + fileFormat=FileFormat.CSV, + filePath=FilePath(root='bucket', path='data', fileName='users.csv'), + destination=Table(path=['project'], tableName='users'), + importOptions=ImportOptions(...) + ) + """ + + def __init__(self, storage: MockStorageBackend): + super().__init__(storage) + + def handle( + self, + command: table_pb2.TableImportFromFileCommand, + credentials, + runtime_options: common_pb2.RuntimeOptions + ) -> table_pb2.TableImportResponse: + """ + Handle TableImportFromFileCommand. + + Args: + command: TableImportFromFileCommand message + credentials: Backend credentials (unused in mock) + runtime_options: Runtime options + + Returns: + TableImportResponse with import statistics + + Raises: + KeyError: If destination table doesn't exist + ValueError: If parameters are invalid + """ + self.validate_runtime_options(runtime_options) + + # Extract destination table info + dest = command.destination + path = list(dest.path) + table_name = dest.tableName + + self.validate_table_path(path, table_name) + table_path_str = self.format_table_path(path, table_name) + + # Get file info for logging + file_info = f"{command.filePath.root}/{command.filePath.path}/{command.filePath.fileName}" + + self.log_info( + f"Importing data from {file_info} into table {table_path_str}" + ) + + # TODO: In a real implementation, this would: + # 1. Read credentials from command.fileCredentials + # 2. Connect to cloud storage (S3/GCS/ABS) + # 3. Download and parse the file + # 4. Insert data into the backend database + + # For this mock, we'll generate some sample data + try: + # Get table schema + schema = self.storage.get_table_schema(path, table_name) + + # Generate mock rows + mock_rows = self._generate_mock_data(schema.columns, num_rows=100) + + # Insert rows + imported_count = self.storage.insert_rows(path, table_name, mock_rows) + + # Get updated table stats + updated_schema = self.storage.get_table_schema(path, table_name) + + self.log_info( + f"Imported {imported_count} rows into {table_path_str}. " + f"Total rows: {updated_schema.row_count}" + ) + + # Build response + response = table_pb2.TableImportResponse() + response.importedRowsCount = imported_count + response.tableRowsCount = updated_schema.row_count + response.tableSizeBytes = updated_schema.size_bytes + + # Add column names + response.importedColumns.extend([col.name for col in schema.columns]) + + # Add timer for demonstration + timer = response.timers.add() + timer.name = "import" + timer.duration = "1.5s" + + return response + + except KeyError: + error_msg = f"Destination table {table_path_str} not found" + self.log_error(error_msg) + raise KeyError(error_msg) + except Exception as e: + self.handle_error(e) + raise + + def _generate_mock_data( + self, + columns: List[ColumnSchema], + num_rows: int = 100 + ) -> List[Dict[str, Any]]: + """ + Generate mock data for demonstration purposes. + + In a real implementation, this would read actual data from files. + + Args: + columns: Table column schemas + num_rows: Number of rows to generate + + Returns: + List of row dictionaries + """ + rows = [] + for i in range(num_rows): + row = {} + for col in columns: + # Generate simple mock data based on type + if col.type.upper() in ('INTEGER', 'INT', 'BIGINT'): + row[col.name] = i + elif col.type.upper() in ('STRING', 'VARCHAR', 'TEXT'): + row[col.name] = f"{col.name}_{i}" + elif col.type.upper() in ('FLOAT', 'DOUBLE', 'DECIMAL'): + row[col.name] = i * 1.5 + elif col.type.upper() == 'BOOLEAN': + row[col.name] = i % 2 == 0 + else: + row[col.name] = f"value_{i}" + rows.append(row) + + return rows diff --git a/packages/php-storage-driver-common/generated-py/examples/storage/__init__.py b/packages/php-storage-driver-common/generated-py/examples/storage/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/php-storage-driver-common/generated-py/examples/storage/mock_storage.py b/packages/php-storage-driver-common/generated-py/examples/storage/mock_storage.py new file mode 100644 index 000000000..2eb5f8c00 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/storage/mock_storage.py @@ -0,0 +1,370 @@ +""" +Mock in-memory storage backend for demonstration purposes. + +This module provides a simple in-memory storage implementation that mimics +a real database backend. It's used for educational purposes to demonstrate +how handlers interact with storage without requiring actual database connections. + +TODO: In production, replace this with real backend implementations: +- BigQuery client for GCP +- Snowflake connector +- Redshift client for AWS +- Teradata connector +- Azure Synapse client +""" + +import logging +from typing import Dict, List, Optional, Any, Tuple +from dataclasses import dataclass, field +from datetime import datetime +import copy + +# Add generated proto modules to path +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from proto import table_pb2, info_pb2 + + +logger = logging.getLogger(__name__) + + +@dataclass +class ColumnSchema: + """Schema definition for a table column.""" + name: str + type: str + length: str = "" + nullable: bool = True + default: Optional[str] = None + + +@dataclass +class TableSchema: + """Schema definition for a table.""" + name: str + path: List[str] + columns: List[ColumnSchema] = field(default_factory=list) + primary_keys: List[str] = field(default_factory=list) + created_at: datetime = field(default_factory=datetime.now) + row_count: int = 0 + size_bytes: int = 0 + + +@dataclass +class TableData: + """Data storage for a table.""" + schema: TableSchema + rows: List[Dict[str, Any]] = field(default_factory=list) + + +class MockStorageBackend: + """ + In-memory storage backend for demonstration purposes. + + This class simulates a database backend with tables, schemas, and data. + It's intentionally simple to focus on the gRPC/protobuf patterns rather + than database complexity. + + Attributes: + tables: Dictionary mapping table paths to TableData + + Example: + >>> storage = MockStorageBackend() + >>> storage.create_table(['project'], 'users', columns) + >>> storage.insert_rows(['project'], 'users', rows) + >>> data = storage.query_table(['project'], 'users', limit=10) + """ + + def __init__(self): + """Initialize the mock storage backend.""" + self.tables: Dict[str, TableData] = {} + logger.info("Mock storage backend initialized") + + def _get_table_key(self, path: List[str], table_name: str) -> str: + """Generate a unique key for a table.""" + return '.'.join(list(path) + [table_name]) + + def table_exists(self, path: List[str], table_name: str) -> bool: + """ + Check if a table exists. + + Args: + path: Table path components + table_name: Table name + + Returns: + True if table exists, False otherwise + """ + key = self._get_table_key(path, table_name) + return key in self.tables + + def create_table( + self, + path: List[str], + table_name: str, + columns: List[ColumnSchema], + primary_keys: Optional[List[str]] = None + ) -> None: + """ + Create a new table. + + Args: + path: Table path components (e.g., ['project', 'bucket']) + table_name: Name of the table + columns: List of column schemas + primary_keys: Optional list of primary key column names + + Raises: + ValueError: If table already exists or invalid parameters + """ + key = self._get_table_key(path, table_name) + + if self.table_exists(path, table_name): + raise ValueError(f"Table {key} already exists") + + if not columns: + raise ValueError("Table must have at least one column") + + # Validate primary keys + if primary_keys: + column_names = {col.name for col in columns} + for pk in primary_keys: + if pk not in column_names: + raise ValueError(f"Primary key column '{pk}' not found in table columns") + + schema = TableSchema( + name=table_name, + path=path, + columns=columns, + primary_keys=primary_keys or [] + ) + + self.tables[key] = TableData(schema=schema, rows=[]) + logger.info(f"Created table {key} with {len(columns)} columns") + + def drop_table(self, path: List[str], table_name: str) -> None: + """ + Drop a table. + + Args: + path: Table path components + table_name: Table name + + Raises: + KeyError: If table doesn't exist + """ + key = self._get_table_key(path, table_name) + + if not self.table_exists(path, table_name): + raise KeyError(f"Table {key} does not exist") + + del self.tables[key] + logger.info(f"Dropped table {key}") + + def get_table_schema(self, path: List[str], table_name: str) -> TableSchema: + """ + Get table schema. + + Args: + path: Table path components + table_name: Table name + + Returns: + TableSchema + + Raises: + KeyError: If table doesn't exist + """ + key = self._get_table_key(path, table_name) + + if not self.table_exists(path, table_name): + raise KeyError(f"Table {key} does not exist") + + return self.tables[key].schema + + def insert_rows( + self, + path: List[str], + table_name: str, + rows: List[Dict[str, Any]] + ) -> int: + """ + Insert rows into a table. + + Args: + path: Table path components + table_name: Table name + rows: List of row dictionaries + + Returns: + Number of rows inserted + + Raises: + KeyError: If table doesn't exist + """ + key = self._get_table_key(path, table_name) + + if not self.table_exists(path, table_name): + raise KeyError(f"Table {key} does not exist") + + table_data = self.tables[key] + + # Validate row columns match table schema + column_names = {col.name for col in table_data.schema.columns} + for i, row in enumerate(rows): + for col in row.keys(): + if col not in column_names: + raise ValueError(f"Row {i}: Column '{col}' not in table schema") + + # Insert rows + table_data.rows.extend(copy.deepcopy(rows)) + table_data.schema.row_count = len(table_data.rows) + + # Estimate size (very rough) + table_data.schema.size_bytes = len(str(table_data.rows).encode()) + + logger.info(f"Inserted {len(rows)} rows into table {key}") + return len(rows) + + def query_table( + self, + path: List[str], + table_name: str, + columns: Optional[List[str]] = None, + limit: Optional[int] = None, + where: Optional[Dict[str, Any]] = None + ) -> Tuple[List[Dict[str, Any]], TableSchema]: + """ + Query table data. + + Args: + path: Table path components + table_name: Table name + columns: Optional list of columns to return (default: all) + limit: Optional limit on number of rows + where: Optional simple filter conditions + + Returns: + Tuple of (rows, schema) + + Raises: + KeyError: If table doesn't exist + """ + key = self._get_table_key(path, table_name) + + if not self.table_exists(path, table_name): + raise KeyError(f"Table {key} does not exist") + + table_data = self.tables[key] + result_rows = copy.deepcopy(table_data.rows) + + # Apply simple where filters + if where: + filtered_rows = [] + for row in result_rows: + match = True + for col, value in where.items(): + if col not in row or row[col] != value: + match = False + break + if match: + filtered_rows.append(row) + result_rows = filtered_rows + + # Apply column selection + if columns: + result_rows = [ + {col: row.get(col) for col in columns} + for row in result_rows + ] + + # Apply limit + if limit and limit > 0: + result_rows = result_rows[:limit] + + return result_rows, table_data.schema + + def execute_query(self, sql: str) -> List[Dict[str, Any]]: + """ + Execute a SQL-like query (very simplified). + + This is a mock implementation that only supports very basic queries. + In a real implementation, this would use the actual database's SQL engine. + + Args: + sql: SQL query string + + Returns: + List of result rows + + Note: + This mock implementation only supports basic SELECT statements + for demonstration purposes. + """ + # Very simple query parser for demonstration + sql_lower = sql.lower().strip() + + if sql_lower.startswith('select'): + # Mock: return empty result + logger.info(f"Executing query: {sql}") + return [] + else: + raise ValueError(f"Unsupported query type: {sql}") + + def get_table_info(self, path: List[str], table_name: str) -> dict: + """ + Get table metadata. + + Args: + path: Table path components + table_name: Table name + + Returns: + Dictionary with table metadata + + Raises: + KeyError: If table doesn't exist + """ + schema = self.get_table_schema(path, table_name) + + return { + 'name': schema.name, + 'path': '.'.join(schema.path), + 'columns': [ + { + 'name': col.name, + 'type': col.type, + 'nullable': col.nullable + } + for col in schema.columns + ], + 'primary_keys': schema.primary_keys, + 'row_count': schema.row_count, + 'size_bytes': schema.size_bytes, + 'created_at': schema.created_at.isoformat() + } + + def list_tables(self, path_prefix: Optional[List[str]] = None) -> List[str]: + """ + List all tables, optionally filtered by path prefix. + + Args: + path_prefix: Optional path prefix to filter tables + + Returns: + List of table keys + """ + if path_prefix: + prefix = '.'.join(path_prefix) + return [ + key for key in self.tables.keys() + if key.startswith(prefix) + ] + return list(self.tables.keys()) + + def clear_all(self) -> None: + """Clear all tables from storage.""" + self.tables.clear() + logger.info("Cleared all tables from storage") diff --git a/packages/php-storage-driver-common/generated-py/examples/tests/__init__.py b/packages/php-storage-driver-common/generated-py/examples/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/php-storage-driver-common/generated-py/examples/utils.py b/packages/php-storage-driver-common/generated-py/examples/utils.py new file mode 100644 index 000000000..5e7920407 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/examples/utils.py @@ -0,0 +1,253 @@ +""" +Utility functions for the gRPC server example. + +This module provides helper functions for logging, protobuf message handling, +and common operations. +""" + +import logging +from typing import Optional, List +from google.protobuf.message import Message +from google.protobuf import any_pb2 + +# Add generated proto modules to path +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).parent.parent)) + +from proto import common_pb2 + + +# Set up module logger +logger = logging.getLogger(__name__) + + +def setup_logging(level: int = logging.INFO) -> None: + """ + Configure logging for the application. + + Args: + level: Logging level (e.g., logging.INFO, logging.DEBUG) + """ + logging.basicConfig( + level=level, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S' + ) + + +def create_log_message( + level: common_pb2.LogMessage.Level, + message: str, + context: Optional[Message] = None +) -> common_pb2.LogMessage: + """ + Create a LogMessage for inclusion in DriverResponse. + + Args: + level: Log level (Emergency, Alert, Critical, Error, Warning, Notice, Informational, Debug) + message: Log message text + context: Optional context as a protobuf Message + + Returns: + LogMessage instance + + Example: + >>> log = create_log_message( + ... common_pb2.LogMessage.Level.Informational, + ... "Table created successfully" + ... ) + """ + log_msg = common_pb2.LogMessage() + log_msg.level = level + log_msg.message = message + + if context: + log_msg.context.Pack(context) + + return log_msg + + +def pack_message(message: Message) -> any_pb2.Any: + """ + Pack a protobuf message into google.protobuf.Any. + + Args: + message: Protobuf message to pack + + Returns: + Any containing the packed message + + Example: + >>> from proto import table_pb2 + >>> cmd = table_pb2.CreateTableCommand() + >>> cmd.tableName = "users" + >>> any_msg = pack_message(cmd) + """ + any_msg = any_pb2.Any() + any_msg.Pack(message) + return any_msg + + +def unpack_message(any_msg: any_pb2.Any, target_class) -> Optional[Message]: + """ + Unpack google.protobuf.Any into a specific message type. + + Args: + any_msg: Any message to unpack + target_class: Target protobuf message class + + Returns: + Unpacked message or None if unpacking fails + + Example: + >>> from proto import table_pb2 + >>> cmd = table_pb2.CreateTableCommand() + >>> unpacked = unpack_message(any_msg, table_pb2.CreateTableCommand) + """ + try: + message = target_class() + if any_msg.Unpack(message): + return message + return None + except Exception as e: + logger.error(f"Failed to unpack message: {e}") + return None + + +def get_type_name(any_msg: any_pb2.Any) -> str: + """ + Extract the type name from a google.protobuf.Any message. + + Args: + any_msg: Any message + + Returns: + Type name (e.g., "CreateTableCommand") + + Example: + >>> type_name = get_type_name(any_msg) + >>> print(type_name) + CreateTableCommand + """ + # type_url format: "type.googleapis.com/package.MessageType" + # We extract the last part after the last '/' + return any_msg.type_url.split('/')[-1] + + +def format_table_path(path: List[str], table_name: str) -> str: + """ + Format a table path for display. + + Args: + path: List of path components (e.g., ['project', 'bucket']) + table_name: Table name + + Returns: + Formatted path string + + Example: + >>> format_table_path(['my-project', 'my-bucket'], 'users') + 'my-project.my-bucket.users' + """ + return '.'.join(list(path) + [table_name]) + + +def validate_table_path(path: List[str], table_name: str) -> tuple[bool, Optional[str]]: + """ + Validate a table path. + + Args: + path: List of path components + table_name: Table name + + Returns: + Tuple of (is_valid, error_message) + + Example: + >>> valid, error = validate_table_path(['project'], 'users') + >>> if not valid: + ... print(error) + """ + if not path: + return False, "Path cannot be empty" + + if not table_name or not table_name.strip(): + return False, "Table name cannot be empty" + + # Check for valid characters (alphanumeric, underscore, hyphen) + for component in path: + if not component or not component.strip(): + return False, "Path components cannot be empty" + + if not table_name.replace('_', '').replace('-', '').isalnum(): + return False, f"Invalid table name: {table_name}" + + return True, None + + +class LogMessageCollector: + """ + Collector for LogMessage instances during command handling. + + This class provides a convenient way to collect log messages + that will be included in the DriverResponse. + + Example: + >>> collector = LogMessageCollector() + >>> collector.info("Table created") + >>> collector.warning("Table already exists, skipping") + >>> messages = collector.get_messages() + """ + + def __init__(self): + self._messages: List[common_pb2.LogMessage] = [] + + def add(self, level: common_pb2.LogMessage.Level, message: str, + context: Optional[Message] = None) -> None: + """Add a log message.""" + self._messages.append(create_log_message(level, message, context)) + + def emergency(self, message: str, context: Optional[Message] = None) -> None: + """Add an emergency level message.""" + self.add(common_pb2.LogMessage.Level.Emergency, message, context) + + def alert(self, message: str, context: Optional[Message] = None) -> None: + """Add an alert level message.""" + self.add(common_pb2.LogMessage.Level.Alert, message, context) + + def critical(self, message: str, context: Optional[Message] = None) -> None: + """Add a critical level message.""" + self.add(common_pb2.LogMessage.Level.Critical, message, context) + + def error(self, message: str, context: Optional[Message] = None) -> None: + """Add an error level message.""" + self.add(common_pb2.LogMessage.Level.Error, message, context) + + def warning(self, message: str, context: Optional[Message] = None) -> None: + """Add a warning level message.""" + self.add(common_pb2.LogMessage.Level.Warning, message, context) + + def notice(self, message: str, context: Optional[Message] = None) -> None: + """Add a notice level message.""" + self.add(common_pb2.LogMessage.Level.Notice, message, context) + + def info(self, message: str, context: Optional[Message] = None) -> None: + """Add an informational level message.""" + self.add(common_pb2.LogMessage.Level.Informational, message, context) + + def debug(self, message: str, context: Optional[Message] = None) -> None: + """Add a debug level message.""" + self.add(common_pb2.LogMessage.Level.Debug, message, context) + + def get_messages(self) -> List[common_pb2.LogMessage]: + """Get all collected log messages.""" + return self._messages + + def clear(self) -> None: + """Clear all collected messages.""" + self._messages.clear() + + def __len__(self) -> int: + """Return the number of collected messages.""" + return len(self._messages) diff --git a/packages/php-storage-driver-common/generated-py/proto/backend/bigQuery_pb2.py b/packages/php-storage-driver-common/generated-py/proto/backend/bigQuery_pb2.py new file mode 100644 index 000000000..e075ac6f0 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/backend/bigQuery_pb2.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/backend/bigQuery.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/backend/bigQuery.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cproto/backend/bigQuery.proto\x12&keboola.storageDriver.backend.bigQuery\"E\n\x10TimePartitioning\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x0c\x65xpirationMs\x18\x02 \x01(\t\x12\r\n\x05\x66ield\x18\x03 \x01(\t\"\xa9\x01\n\x11RangePartitioning\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12N\n\x05range\x18\x02 \x01(\x0b\x32?.keboola.storageDriver.backend.bigQuery.RangePartitioning.Range\x1a\x35\n\x05Range\x12\r\n\x05start\x18\x01 \x01(\t\x12\x0b\n\x03\x65nd\x18\x02 \x01(\t\x12\x10\n\x08interval\x18\x03 \x01(\t\"\x1c\n\nClustering\x12\x0e\n\x06\x66ields\x18\x01 \x03(\tb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.backend.bigQuery_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_TIMEPARTITIONING']._serialized_start=72 + _globals['_TIMEPARTITIONING']._serialized_end=141 + _globals['_RANGEPARTITIONING']._serialized_start=144 + _globals['_RANGEPARTITIONING']._serialized_end=313 + _globals['_RANGEPARTITIONING_RANGE']._serialized_start=260 + _globals['_RANGEPARTITIONING_RANGE']._serialized_end=313 + _globals['_CLUSTERING']._serialized_start=315 + _globals['_CLUSTERING']._serialized_end=343 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/backend/bigQuery_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/backend/bigQuery_pb2_grpc.py new file mode 100644 index 000000000..6f0cb87b6 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/backend/bigQuery_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/backend/bigQuery_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/backend_pb2.py b/packages/php-storage-driver-common/generated-py/proto/backend_pb2.py new file mode 100644 index 000000000..988aa110c --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/backend_pb2.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/backend.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/backend.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13proto/backend.proto\x12%keboola.storageDriver.command.backend\x1a\x19google/protobuf/any.proto\"8\n\x12InitBackendCommand\x12\"\n\x04meta\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\"k\n\x13InitBackendResponse\x12\"\n\x04meta\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\x30\n\x16InitBackendSynapseMeta\x12\x16\n\x0eglobalRoleName\x18\x01 \x01(\t\":\n\x14RemoveBackendCommand\x12\"\n\x04meta\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Anyb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.backend_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_INITBACKENDCOMMAND']._serialized_start=89 + _globals['_INITBACKENDCOMMAND']._serialized_end=145 + _globals['_INITBACKENDRESPONSE']._serialized_start=147 + _globals['_INITBACKENDRESPONSE']._serialized_end=254 + _globals['_INITBACKENDRESPONSE_INITBACKENDSYNAPSEMETA']._serialized_start=206 + _globals['_INITBACKENDRESPONSE_INITBACKENDSYNAPSEMETA']._serialized_end=254 + _globals['_REMOVEBACKENDCOMMAND']._serialized_start=256 + _globals['_REMOVEBACKENDCOMMAND']._serialized_end=314 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/backend_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/backend_pb2_grpc.py new file mode 100644 index 000000000..a1fa28cf9 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/backend_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/backend_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/bucket_pb2.py b/packages/php-storage-driver-common/generated-py/proto/bucket_pb2.py new file mode 100644 index 000000000..943938063 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/bucket_pb2.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/bucket.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/bucket.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12proto/bucket.proto\x12$keboola.storageDriver.command.bucket\x1a\x19google/protobuf/any.proto\"\xee\x02\n\x13\x43reateBucketCommand\x12\x13\n\x0bstackPrefix\x18\x01 \x01(\t\x12\x11\n\tprojectId\x18\x02 \x01(\t\x12\x10\n\x08\x62ucketId\x18\x03 \x01(\t\x12\x10\n\x08\x62ranchId\x18\x07 \x01(\t\x12\x17\n\x0fprojectRoleName\x18\x04 \x01(\t\x12\x1f\n\x17projectReadOnlyRoleName\x18\x05 \x01(\t\x12!\n\x19\x64\x65vBranchReadOnlyRoleName\x18\x08 \x01(\t\x12\x17\n\x0fisBranchDefault\x18\t \x01(\x08\x12\"\n\x04meta\x18\x06 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\x41\n\x18\x43reateBucketTeradataMeta\x12\x11\n\tpermSpace\x18\x01 \x01(\t\x12\x12\n\nspoolSpace\x18\x02 \x01(\t\x1a.\n\x18\x43reateBucketBigqueryMeta\x12\x12\n\x06region\x18\x01 \x01(\tB\x02\x18\x01\"D\n\x14\x43reateBucketResponse\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x1e\n\x16\x63reateBucketObjectName\x18\x02 \x01(\t\"\x9f\x01\n\x11\x44ropBucketCommand\x12\x18\n\x10\x62ucketObjectName\x18\x01 \x01(\t\x12\x18\n\x0cignoreErrors\x18\x02 \x01(\x08\x42\x02\x18\x01\x12\x1f\n\x17projectReadOnlyRoleName\x18\x03 \x01(\t\x12\"\n\x04meta\x18\x04 \x01(\x0b\x32\x14.google.protobuf.Any\x12\x11\n\tisCascade\x18\x05 \x01(\x08\"\xef\x01\n\x11LinkBucketCommand\x12\x13\n\x0bstackPrefix\x18\x01 \x01(\t\x12\x17\n\x0ftargetProjectId\x18\x02 \x01(\t\x12\x16\n\x0etargetBucketId\x18\x03 \x01(\t\x12\x1b\n\x13sourceShareRoleName\x18\x04 \x01(\t\x12%\n\x1dtargetProjectReadOnlyRoleName\x18\x05 \x01(\t\x12\"\n\x04meta\x18\x06 \x01(\x0b\x32\x14.google.protobuf.Any\x1a,\n\x16LinkBucketBigqueryMeta\x12\x12\n\x06region\x18\x01 \x01(\tB\x02\x18\x01\"6\n\x14LinkedBucketResponse\x12\x1e\n\x16linkedBucketObjectName\x18\x01 \x01(\t\"\xb4\x02\n\x12ShareBucketCommand\x12\x13\n\x0bstackPrefix\x18\x01 \x01(\t\x12\x1e\n\x16sourceBucketObjectName\x18\x02 \x01(\t\x12%\n\x1dsourceProjectReadOnlyRoleName\x18\x03 \x01(\t\x12\x17\n\x0fsourceProjectId\x18\x04 \x01(\t\x12\x16\n\x0esourceBucketId\x18\x05 \x01(\t\x12\"\n\x04meta\x18\x06 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\x37\n\x1fShareBucketSnowflakeCommandMeta\x12\x14\n\x0c\x64\x61tabaseName\x18\x01 \x01(\t\x1a\x34\n\x1eShareBucketBigqueryCommandMeta\x12\x12\n\x06region\x18\x01 \x01(\tB\x02\x18\x01\"2\n\x13ShareBucketResponse\x12\x1b\n\x13\x62ucketShareRoleName\x18\x01 \x01(\t\"\x91\x01\n\x13UnlinkBucketCommand\x12\x18\n\x10\x62ucketObjectName\x18\x01 \x01(\t\x12\x1b\n\x13sourceShareRoleName\x18\x02 \x01(\t\x12\x1f\n\x17projectReadOnlyRoleName\x18\x03 \x01(\t\x12\"\n\x04meta\x18\x04 \x01(\x0b\x32\x14.google.protobuf.Any\"\x92\x01\n\x14UnshareBucketCommand\x12\x18\n\x10\x62ucketObjectName\x18\x01 \x01(\t\x12\x1b\n\x13\x62ucketShareRoleName\x18\x02 \x01(\t\x12\x1f\n\x17projectReadOnlyRoleName\x18\x03 \x01(\t\x12\"\n\x04meta\x18\x04 \x01(\x0b\x32\x14.google.protobuf.Any\"\x84\x02\n&GrantBucketAccessToReadOnlyRoleCommand\x12\x1f\n\x17projectReadOnlyRoleName\x18\x02 \x01(\t\x12\"\n\x04meta\x18\x03 \x01(\x0b\x32\x14.google.protobuf.Any\x12\x10\n\x08\x62ranchId\x18\x04 \x01(\t\x12\x13\n\x0bstackPrefix\x18\x05 \x01(\t\x12\x1d\n\x15\x64\x65stinationObjectName\x18\x06 \x01(\t\x12\x0c\n\x04path\x18\x07 \x03(\t\x1a\x41\n+GrantBucketAccessToReadOnlyRoleBigqueryMeta\x12\x12\n\x06region\x18\x01 \x01(\tB\x02\x18\x01\"I\n\'GrantBucketAccessToReadOnlyRoleResponse\x12\x1e\n\x16\x63reateBucketObjectName\x18\x01 \x01(\t\"\xa4\x01\n)RevokeBucketAccessFromReadOnlyRoleCommand\x12\x18\n\x10\x62ucketObjectName\x18\x01 \x01(\t\x12\x1f\n\x17projectReadOnlyRoleName\x18\x02 \x01(\t\x12\x18\n\x0cignoreErrors\x18\x03 \x01(\x08\x42\x02\x18\x01\x12\"\n\x04meta\x18\x04 \x01(\x0b\x32\x14.google.protobuf.Anyb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.bucket_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CREATEBUCKETCOMMAND_CREATEBUCKETBIGQUERYMETA'].fields_by_name['region']._loaded_options = None + _globals['_CREATEBUCKETCOMMAND_CREATEBUCKETBIGQUERYMETA'].fields_by_name['region']._serialized_options = b'\030\001' + _globals['_DROPBUCKETCOMMAND'].fields_by_name['ignoreErrors']._loaded_options = None + _globals['_DROPBUCKETCOMMAND'].fields_by_name['ignoreErrors']._serialized_options = b'\030\001' + _globals['_LINKBUCKETCOMMAND_LINKBUCKETBIGQUERYMETA'].fields_by_name['region']._loaded_options = None + _globals['_LINKBUCKETCOMMAND_LINKBUCKETBIGQUERYMETA'].fields_by_name['region']._serialized_options = b'\030\001' + _globals['_SHAREBUCKETCOMMAND_SHAREBUCKETBIGQUERYCOMMANDMETA'].fields_by_name['region']._loaded_options = None + _globals['_SHAREBUCKETCOMMAND_SHAREBUCKETBIGQUERYCOMMANDMETA'].fields_by_name['region']._serialized_options = b'\030\001' + _globals['_GRANTBUCKETACCESSTOREADONLYROLECOMMAND_GRANTBUCKETACCESSTOREADONLYROLEBIGQUERYMETA'].fields_by_name['region']._loaded_options = None + _globals['_GRANTBUCKETACCESSTOREADONLYROLECOMMAND_GRANTBUCKETACCESSTOREADONLYROLEBIGQUERYMETA'].fields_by_name['region']._serialized_options = b'\030\001' + _globals['_REVOKEBUCKETACCESSFROMREADONLYROLECOMMAND'].fields_by_name['ignoreErrors']._loaded_options = None + _globals['_REVOKEBUCKETACCESSFROMREADONLYROLECOMMAND'].fields_by_name['ignoreErrors']._serialized_options = b'\030\001' + _globals['_CREATEBUCKETCOMMAND']._serialized_start=88 + _globals['_CREATEBUCKETCOMMAND']._serialized_end=454 + _globals['_CREATEBUCKETCOMMAND_CREATEBUCKETTERADATAMETA']._serialized_start=341 + _globals['_CREATEBUCKETCOMMAND_CREATEBUCKETTERADATAMETA']._serialized_end=406 + _globals['_CREATEBUCKETCOMMAND_CREATEBUCKETBIGQUERYMETA']._serialized_start=408 + _globals['_CREATEBUCKETCOMMAND_CREATEBUCKETBIGQUERYMETA']._serialized_end=454 + _globals['_CREATEBUCKETRESPONSE']._serialized_start=456 + _globals['_CREATEBUCKETRESPONSE']._serialized_end=524 + _globals['_DROPBUCKETCOMMAND']._serialized_start=527 + _globals['_DROPBUCKETCOMMAND']._serialized_end=686 + _globals['_LINKBUCKETCOMMAND']._serialized_start=689 + _globals['_LINKBUCKETCOMMAND']._serialized_end=928 + _globals['_LINKBUCKETCOMMAND_LINKBUCKETBIGQUERYMETA']._serialized_start=884 + _globals['_LINKBUCKETCOMMAND_LINKBUCKETBIGQUERYMETA']._serialized_end=928 + _globals['_LINKEDBUCKETRESPONSE']._serialized_start=930 + _globals['_LINKEDBUCKETRESPONSE']._serialized_end=984 + _globals['_SHAREBUCKETCOMMAND']._serialized_start=987 + _globals['_SHAREBUCKETCOMMAND']._serialized_end=1295 + _globals['_SHAREBUCKETCOMMAND_SHAREBUCKETSNOWFLAKECOMMANDMETA']._serialized_start=1186 + _globals['_SHAREBUCKETCOMMAND_SHAREBUCKETSNOWFLAKECOMMANDMETA']._serialized_end=1241 + _globals['_SHAREBUCKETCOMMAND_SHAREBUCKETBIGQUERYCOMMANDMETA']._serialized_start=1243 + _globals['_SHAREBUCKETCOMMAND_SHAREBUCKETBIGQUERYCOMMANDMETA']._serialized_end=1295 + _globals['_SHAREBUCKETRESPONSE']._serialized_start=1297 + _globals['_SHAREBUCKETRESPONSE']._serialized_end=1347 + _globals['_UNLINKBUCKETCOMMAND']._serialized_start=1350 + _globals['_UNLINKBUCKETCOMMAND']._serialized_end=1495 + _globals['_UNSHAREBUCKETCOMMAND']._serialized_start=1498 + _globals['_UNSHAREBUCKETCOMMAND']._serialized_end=1644 + _globals['_GRANTBUCKETACCESSTOREADONLYROLECOMMAND']._serialized_start=1647 + _globals['_GRANTBUCKETACCESSTOREADONLYROLECOMMAND']._serialized_end=1907 + _globals['_GRANTBUCKETACCESSTOREADONLYROLECOMMAND_GRANTBUCKETACCESSTOREADONLYROLEBIGQUERYMETA']._serialized_start=1842 + _globals['_GRANTBUCKETACCESSTOREADONLYROLECOMMAND_GRANTBUCKETACCESSTOREADONLYROLEBIGQUERYMETA']._serialized_end=1907 + _globals['_GRANTBUCKETACCESSTOREADONLYROLERESPONSE']._serialized_start=1909 + _globals['_GRANTBUCKETACCESSTOREADONLYROLERESPONSE']._serialized_end=1982 + _globals['_REVOKEBUCKETACCESSFROMREADONLYROLECOMMAND']._serialized_start=1985 + _globals['_REVOKEBUCKETACCESSFROMREADONLYROLECOMMAND']._serialized_end=2149 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/bucket_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/bucket_pb2_grpc.py new file mode 100644 index 000000000..594257444 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/bucket_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/bucket_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/common_pb2.py b/packages/php-storage-driver-common/generated-py/proto/common_pb2.py new file mode 100644 index 000000000..a177d7925 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/common_pb2.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/common.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/common.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12proto/common.proto\x12$keboola.storageDriver.command.common\x1a\x19google/protobuf/any.proto\"\xc1\x01\n\rDriverRequest\x12)\n\x0b\x63redentials\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\x12%\n\x07\x63ommand\x18\x02 \x01(\x0b\x32\x14.google.protobuf.Any\x12\x10\n\x08\x66\x65\x61tures\x18\x03 \x03(\t\x12L\n\x0eruntimeOptions\x18\x04 \x01(\x0b\x32\x34.keboola.storageDriver.command.common.RuntimeOptions\"\xcd\x01\n\x0eRuntimeOptions\x12\r\n\x05runId\x18\x01 \x01(\t\x12V\n\tqueryTags\x18\x03 \x03(\x0b\x32\x43.keboola.storageDriver.command.common.RuntimeOptions.QueryTagsEntry\x12\"\n\x04meta\x18\x02 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\x30\n\x0eQueryTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xfe\x01\n\nLogMessage\x12\x45\n\x05level\x18\x01 \x01(\x0e\x32\x36.keboola.storageDriver.command.common.LogMessage.Level\x12\x0f\n\x07message\x18\x02 \x01(\t\x12%\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x14.google.protobuf.Any\"q\n\x05Level\x12\r\n\tEmergency\x10\x00\x12\t\n\x05\x41lert\x10\x01\x12\x0c\n\x08\x43ritical\x10\x02\x12\t\n\x05\x45rror\x10\x03\x12\x0b\n\x07Warning\x10\x04\x12\n\n\x06Notice\x10\x05\x12\x11\n\rInformational\x10\x06\x12\t\n\x05\x44\x65\x62ug\x10\x07\"\x83\x01\n\x0e\x44riverResponse\x12-\n\x0f\x63ommandResponse\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\x12\x42\n\x08messages\x18\x02 \x03(\x0b\x32\x30.keboola.storageDriver.command.common.LogMessageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.common_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_RUNTIMEOPTIONS_QUERYTAGSENTRY']._loaded_options = None + _globals['_RUNTIMEOPTIONS_QUERYTAGSENTRY']._serialized_options = b'8\001' + _globals['_DRIVERREQUEST']._serialized_start=88 + _globals['_DRIVERREQUEST']._serialized_end=281 + _globals['_RUNTIMEOPTIONS']._serialized_start=284 + _globals['_RUNTIMEOPTIONS']._serialized_end=489 + _globals['_RUNTIMEOPTIONS_QUERYTAGSENTRY']._serialized_start=441 + _globals['_RUNTIMEOPTIONS_QUERYTAGSENTRY']._serialized_end=489 + _globals['_LOGMESSAGE']._serialized_start=492 + _globals['_LOGMESSAGE']._serialized_end=746 + _globals['_LOGMESSAGE_LEVEL']._serialized_start=633 + _globals['_LOGMESSAGE_LEVEL']._serialized_end=746 + _globals['_DRIVERRESPONSE']._serialized_start=749 + _globals['_DRIVERRESPONSE']._serialized_end=880 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/common_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/common_pb2_grpc.py new file mode 100644 index 000000000..9a6b996a0 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/common_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/common_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/credentials_pb2.py b/packages/php-storage-driver-common/generated-py/proto/credentials_pb2.py new file mode 100644 index 000000000..c9ec57f79 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/credentials_pb2.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/credentials.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/credentials.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17proto/credentials.proto\x12!keboola.storageDriver.credentials\x1a\x19google/protobuf/any.proto\"\xdf\x03\n\x19GenericBackendCredentials\x12\x0c\n\x04host\x18\x01 \x01(\t\x12\x11\n\tprincipal\x18\x02 \x01(\t\x12\x0e\n\x06secret\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\r\x12\"\n\x04meta\x18\x05 \x01(\x0b\x32\x14.google.protobuf.Any\x1a+\n\x17RedshiftCredentialsMeta\x12\x10\n\x08\x64\x61tabase\x18\x01 \x01(\t\x1a+\n\x17TeradataCredentialsMeta\x12\x10\n\x08\x64\x61tabase\x18\x01 \x01(\t\x1a\x7f\n\x18SnowflakeCredentialsMeta\x12\x10\n\x08\x64\x61tabase\x18\x01 \x01(\t\x12\x11\n\twarehouse\x18\x02 \x01(\t\x12(\n workspaceStatementTimeoutSeconds\x18\x03 \x01(\r\x12\x14\n\x0ctracingLevel\x18\x04 \x01(\r\x1a\x46\n\x16SynapseCredentialsMeta\x12\x10\n\x08\x64\x61tabase\x18\x01 \x01(\t\x12\x1a\n\x12useManagedIdentity\x18\x02 \x01(\x08\x1a<\n\x17\x42igQueryCredentialsMeta\x12\x11\n\tfolder_id\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\tb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.credentials_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_GENERICBACKENDCREDENTIALS']._serialized_start=90 + _globals['_GENERICBACKENDCREDENTIALS']._serialized_end=569 + _globals['_GENERICBACKENDCREDENTIALS_REDSHIFTCREDENTIALSMETA']._serialized_start=218 + _globals['_GENERICBACKENDCREDENTIALS_REDSHIFTCREDENTIALSMETA']._serialized_end=261 + _globals['_GENERICBACKENDCREDENTIALS_TERADATACREDENTIALSMETA']._serialized_start=263 + _globals['_GENERICBACKENDCREDENTIALS_TERADATACREDENTIALSMETA']._serialized_end=306 + _globals['_GENERICBACKENDCREDENTIALS_SNOWFLAKECREDENTIALSMETA']._serialized_start=308 + _globals['_GENERICBACKENDCREDENTIALS_SNOWFLAKECREDENTIALSMETA']._serialized_end=435 + _globals['_GENERICBACKENDCREDENTIALS_SYNAPSECREDENTIALSMETA']._serialized_start=437 + _globals['_GENERICBACKENDCREDENTIALS_SYNAPSECREDENTIALSMETA']._serialized_end=507 + _globals['_GENERICBACKENDCREDENTIALS_BIGQUERYCREDENTIALSMETA']._serialized_start=509 + _globals['_GENERICBACKENDCREDENTIALS_BIGQUERYCREDENTIALSMETA']._serialized_end=569 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/credentials_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/credentials_pb2_grpc.py new file mode 100644 index 000000000..ea711a922 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/credentials_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/credentials_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/executeQuery_pb2.py b/packages/php-storage-driver-common/generated-py/proto/executeQuery_pb2.py new file mode 100644 index 000000000..c97c347ff --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/executeQuery_pb2.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/executeQuery.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/executeQuery.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18proto/executeQuery.proto\x12*keboola.storageDriver.command.executeQuery\"\xac\x03\n\x13\x45xecuteQueryCommand\x12\x17\n\x0fpathRestriction\x18\x01 \x03(\t\x12\x0f\n\x07timeout\x18\x02 \x01(\r\x12\r\n\x05query\x18\x03 \x01(\t\x12\x66\n\rsnowflakeRole\x18\x04 \x01(\x0b\x32M.keboola.storageDriver.command.executeQuery.ExecuteQueryCommand.SnowflakeRoleH\x00\x12x\n\x16\x62igQueryServiceAccount\x18\x05 \x01(\x0b\x32V.keboola.storageDriver.command.executeQuery.ExecuteQueryCommand.BigQueryServiceAccountH\x00\x1a!\n\rSnowflakeRole\x12\x10\n\x08roleName\x18\x01 \x01(\t\x1aH\n\x16\x42igQueryServiceAccount\x12\x1b\n\x13serviceAccountEmail\x18\x01 \x01(\t\x12\x11\n\tprojectId\x18\x02 \x01(\tB\r\n\x0brestriction\"\x88\x04\n\x14\x45xecuteQueryResponse\x12W\n\x06status\x18\x01 \x01(\x0e\x32G.keboola.storageDriver.command.executeQuery.ExecuteQueryResponse.Status\x12S\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x45.keboola.storageDriver.command.executeQuery.ExecuteQueryResponse.Data\x12\x0f\n\x07message\x18\x03 \x01(\t\x1a\x8e\x02\n\x04\x44\x61ta\x12\x0f\n\x07\x63olumns\x18\x01 \x03(\t\x12W\n\x04rows\x18\x02 \x03(\x0b\x32I.keboola.storageDriver.command.executeQuery.ExecuteQueryResponse.Data.Row\x1a\x9b\x01\n\x03Row\x12\x65\n\x06\x66ields\x18\x01 \x03(\x0b\x32U.keboola.storageDriver.command.executeQuery.ExecuteQueryResponse.Data.Row.FieldsEntry\x1a-\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\" \n\x06Status\x12\x0b\n\x07Success\x10\x00\x12\t\n\x05\x45rror\x10\x01\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.executeQuery_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_EXECUTEQUERYRESPONSE_DATA_ROW_FIELDSENTRY']._loaded_options = None + _globals['_EXECUTEQUERYRESPONSE_DATA_ROW_FIELDSENTRY']._serialized_options = b'8\001' + _globals['_EXECUTEQUERYCOMMAND']._serialized_start=73 + _globals['_EXECUTEQUERYCOMMAND']._serialized_end=501 + _globals['_EXECUTEQUERYCOMMAND_SNOWFLAKEROLE']._serialized_start=379 + _globals['_EXECUTEQUERYCOMMAND_SNOWFLAKEROLE']._serialized_end=412 + _globals['_EXECUTEQUERYCOMMAND_BIGQUERYSERVICEACCOUNT']._serialized_start=414 + _globals['_EXECUTEQUERYCOMMAND_BIGQUERYSERVICEACCOUNT']._serialized_end=486 + _globals['_EXECUTEQUERYRESPONSE']._serialized_start=504 + _globals['_EXECUTEQUERYRESPONSE']._serialized_end=1024 + _globals['_EXECUTEQUERYRESPONSE_DATA']._serialized_start=720 + _globals['_EXECUTEQUERYRESPONSE_DATA']._serialized_end=990 + _globals['_EXECUTEQUERYRESPONSE_DATA_ROW']._serialized_start=835 + _globals['_EXECUTEQUERYRESPONSE_DATA_ROW']._serialized_end=990 + _globals['_EXECUTEQUERYRESPONSE_DATA_ROW_FIELDSENTRY']._serialized_start=945 + _globals['_EXECUTEQUERYRESPONSE_DATA_ROW_FIELDSENTRY']._serialized_end=990 + _globals['_EXECUTEQUERYRESPONSE_STATUS']._serialized_start=992 + _globals['_EXECUTEQUERYRESPONSE_STATUS']._serialized_end=1024 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/executeQuery_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/executeQuery_pb2_grpc.py new file mode 100644 index 000000000..9191020b4 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/executeQuery_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/executeQuery_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/info_pb2.py b/packages/php-storage-driver-common/generated-py/proto/info_pb2.py new file mode 100644 index 000000000..129aebfe1 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/info_pb2.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/info.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/info.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from proto.backend import bigQuery_pb2 as proto_dot_backend_dot_bigQuery__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10proto/info.proto\x12\"keboola.storageDriver.command.info\x1a\x19google/protobuf/any.proto\x1a\x1cproto/backend/bigQuery.proto\"m\n\x11ObjectInfoCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12J\n\x12\x65xpectedObjectType\x18\x02 \x01(\x0e\x32..keboola.storageDriver.command.info.ObjectType\"\x8a\x03\n\x12ObjectInfoResponse\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x42\n\nobjectType\x18\x02 \x01(\x0e\x32..keboola.storageDriver.command.info.ObjectType\x12H\n\x0c\x64\x61tabaseInfo\x18\x03 \x01(\x0b\x32\x30.keboola.storageDriver.command.info.DatabaseInfoH\x00\x12\x44\n\nschemaInfo\x18\x04 \x01(\x0b\x32..keboola.storageDriver.command.info.SchemaInfoH\x00\x12@\n\x08viewInfo\x18\x05 \x01(\x0b\x32,.keboola.storageDriver.command.info.ViewInfoH\x00\x12\x42\n\ttableInfo\x18\x06 \x01(\x0b\x32-.keboola.storageDriver.command.info.TableInfoH\x00\x42\x0c\n\nobjectInfo\"d\n\nObjectInfo\x12\x12\n\nobjectName\x18\x01 \x01(\t\x12\x42\n\nobjectType\x18\x02 \x01(\x0e\x32..keboola.storageDriver.command.info.ObjectType\"O\n\x0c\x44\x61tabaseInfo\x12?\n\x07objects\x18\x01 \x03(\x0b\x32..keboola.storageDriver.command.info.ObjectInfo\"M\n\nSchemaInfo\x12?\n\x07objects\x18\x01 \x03(\x0b\x32..keboola.storageDriver.command.info.ObjectInfo\"\xc7\x01\n\x08ViewInfo\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x10\n\x08viewName\x18\x02 \x01(\t\x12J\n\x07\x63olumns\x18\x03 \x03(\x0b\x32\x39.keboola.storageDriver.command.info.TableInfo.TableColumn\x12\x18\n\x10primaryKeysNames\x18\x04 \x03(\t\x12\x11\n\trowsCount\x18\x05 \x01(\x03\x12\"\n\x04meta\x18\x06 \x01(\x0b\x32\x14.google.protobuf.Any\"\xba\x07\n\tTableInfo\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12J\n\x07\x63olumns\x18\x03 \x03(\x0b\x32\x39.keboola.storageDriver.command.info.TableInfo.TableColumn\x12\x18\n\x10primaryKeysNames\x18\x04 \x03(\t\x12\x11\n\trowsCount\x18\x05 \x01(\x03\x12\x11\n\tsizeBytes\x18\x06 \x01(\x03\x12@\n\ttableType\x18\x07 \x01(\x0e\x32-.keboola.storageDriver.command.info.TableType\x12\"\n\x04meta\x18\x08 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\xac\x01\n\x0bTableColumn\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x0e\n\x06length\x18\x03 \x01(\t\x12\x10\n\x08nullable\x18\x04 \x01(\x08\x12\x0f\n\x07\x64\x65\x66\x61ult\x18\x05 \x01(\t\x12\"\n\x04meta\x18\x06 \x01(\x0b\x32\x14.google.protobuf.Any\x1a*\n\x17TeradataTableColumnMeta\x12\x0f\n\x07isLatin\x18\x01 \x01(\x08\x1a\xea\x03\n\x11\x42igQueryTableMeta\x12R\n\x10timePartitioning\x18\x01 \x01(\x0b\x32\x38.keboola.storageDriver.backend.bigQuery.TimePartitioning\x12T\n\x11rangePartitioning\x18\x02 \x01(\x0b\x32\x39.keboola.storageDriver.backend.bigQuery.RangePartitioning\x12\x1e\n\x16requirePartitionFilter\x18\x03 \x01(\x08\x12\x46\n\nclustering\x18\x04 \x01(\x0b\x32\x32.keboola.storageDriver.backend.bigQuery.Clustering\x12]\n\npartitions\x18\x05 \x03(\x0b\x32I.keboola.storageDriver.command.info.TableInfo.BigQueryTableMeta.Partition\x1a\x64\n\tPartition\x12\x14\n\x0cpartition_id\x18\x01 \x01(\t\x12\x12\n\nrowsNumber\x18\x02 \x01(\t\x12\x18\n\x10lastModifiedTime\x18\x03 \x01(\t\x12\x13\n\x0bstorageTier\x18\x04 \x01(\t*;\n\nObjectType\x12\x0c\n\x08\x44\x41TABASE\x10\x00\x12\n\n\x06SCHEMA\x10\x01\x12\t\n\x05TABLE\x10\x02\x12\x08\n\x04VIEW\x10\x03*%\n\tTableType\x12\n\n\x06NORMAL\x10\x00\x12\x0c\n\x08\x45XTERNAL\x10\x01\x62\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.info_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_OBJECTTYPE']._serialized_start=2042 + _globals['_OBJECTTYPE']._serialized_end=2101 + _globals['_TABLETYPE']._serialized_start=2103 + _globals['_TABLETYPE']._serialized_end=2140 + _globals['_OBJECTINFOCOMMAND']._serialized_start=113 + _globals['_OBJECTINFOCOMMAND']._serialized_end=222 + _globals['_OBJECTINFORESPONSE']._serialized_start=225 + _globals['_OBJECTINFORESPONSE']._serialized_end=619 + _globals['_OBJECTINFO']._serialized_start=621 + _globals['_OBJECTINFO']._serialized_end=721 + _globals['_DATABASEINFO']._serialized_start=723 + _globals['_DATABASEINFO']._serialized_end=802 + _globals['_SCHEMAINFO']._serialized_start=804 + _globals['_SCHEMAINFO']._serialized_end=881 + _globals['_VIEWINFO']._serialized_start=884 + _globals['_VIEWINFO']._serialized_end=1083 + _globals['_TABLEINFO']._serialized_start=1086 + _globals['_TABLEINFO']._serialized_end=2040 + _globals['_TABLEINFO_TABLECOLUMN']._serialized_start=1375 + _globals['_TABLEINFO_TABLECOLUMN']._serialized_end=1547 + _globals['_TABLEINFO_TABLECOLUMN_TERADATATABLECOLUMNMETA']._serialized_start=1505 + _globals['_TABLEINFO_TABLECOLUMN_TERADATATABLECOLUMNMETA']._serialized_end=1547 + _globals['_TABLEINFO_BIGQUERYTABLEMETA']._serialized_start=1550 + _globals['_TABLEINFO_BIGQUERYTABLEMETA']._serialized_end=2040 + _globals['_TABLEINFO_BIGQUERYTABLEMETA_PARTITION']._serialized_start=1940 + _globals['_TABLEINFO_BIGQUERYTABLEMETA_PARTITION']._serialized_end=2040 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/info_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/info_pb2_grpc.py new file mode 100644 index 000000000..1bae64008 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/info_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/info_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/project_pb2.py b/packages/php-storage-driver-common/generated-py/proto/project_pb2.py new file mode 100644 index 000000000..78fa870ba --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/project_pb2.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/project.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/project.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13proto/project.proto\x12%keboola.storageDriver.command.project\x1a\x19google/protobuf/any.proto\"\x91\x05\n\x14\x43reateProjectCommand\x12\x13\n\x0bstackPrefix\x18\x01 \x01(\t\x12\x11\n\tprojectId\x18\x02 \x01(\t\x12\x19\n\x11\x64\x61taRetentionTime\x18\x06 \x01(\x05\x12`\n\x0b\x66ileStorage\x18\x07 \x01(\x0e\x32K.keboola.storageDriver.command.project.CreateProjectCommand.FileStorageType\x12\"\n\x04meta\x18\x05 \x01(\x0b\x32\x14.google.protobuf.Any\x1aX\n\x19\x43reateProjectTeradataMeta\x12\x14\n\x0crootDatabase\x18\x01 \x01(\t\x12\x11\n\tpermSpace\x18\x02 \x01(\t\x12\x12\n\nspoolSpace\x18\x03 \x01(\t\x1aJ\n\x19\x43reateProjectBigqueryMeta\x12\x19\n\x11gcsFileBucketName\x18\x01 \x01(\t\x12\x12\n\x06region\x18\x02 \x01(\tB\x02\x18\x01\x1a\xdc\x01\n\x1a\x43reateProjectSnowflakeMeta\x12\x1e\n\x16storageIntegrationName\x18\x01 \x01(\t\x12\x1c\n\x14projectUserLoginType\x18\x02 \x01(\t\x12\x1c\n\x14projectUserPublicKey\x18\x03 \x01(\t\x12\x1c\n\x14setupDynamicBackends\x18\x04 \x01(\x08\x12\x1f\n\x17\x64\x65\x66\x61ultWarehouseToGrant\x18\x05 \x01(\t\x12#\n\x1b\x61\x64\x64itionalWarehousesToGrant\x18\x06 \x03(\t\"+\n\x0f\x46ileStorageType\x12\x06\n\x02S3\x10\x00\x12\x07\n\x03\x41\x42S\x10\x01\x12\x07\n\x03GCS\x10\x02\"\xfe\x01\n\x15\x43reateProjectResponse\x12\x17\n\x0fprojectUserName\x18\x01 \x01(\t\x12\x17\n\x0fprojectRoleName\x18\x02 \x01(\t\x12\x17\n\x0fprojectPassword\x18\x03 \x01(\t\x12\x1f\n\x17projectReadOnlyRoleName\x18\x04 \x01(\t\x12\x1b\n\x13projectDatabaseName\x18\x08 \x01(\t\x12\"\n\x04meta\x18\x05 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\x38\n\x1a\x43reateProjectSnowflakeMeta\x12\x1a\n\x12isNetworkPolicySet\x18\x01 \x01(\x08\"K\n\x14UpdateProjectCommand\x12\x11\n\tprojectId\x18\x01 \x01(\t\x12\x0e\n\x06region\x18\x02 \x01(\t\x12\x10\n\x08timezone\x18\x03 \x01(\t\"\xeb\x01\n\x12\x44ropProjectCommand\x12\x17\n\x0fprojectUserName\x18\x01 \x01(\t\x12\x17\n\x0fprojectRoleName\x18\x02 \x01(\t\x12\x18\n\x10readOnlyRoleName\x18\x03 \x01(\t\x12\x1b\n\x13projectDatabaseName\x18\x05 \x01(\t\x12\"\n\x04meta\x18\x04 \x01(\x0b\x32\x14.google.protobuf.Any\x1aH\n\x17\x44ropProjectBigqueryMeta\x12\x19\n\x11gcsFileBucketName\x18\x01 \x01(\t\x12\x12\n\x06region\x18\x02 \x01(\tB\x02\x18\x01\"\xb0\x01\n\x16\x43reateDevBranchCommand\x12\x13\n\x0bstackPrefix\x18\x01 \x01(\t\x12\x11\n\tprojectId\x18\x02 \x01(\t\x12\x10\n\x08\x62ranchId\x18\x03 \x01(\t\x12\x17\n\x0fprojectRoleName\x18\x04 \x01(\t\x12\x1f\n\x17projectReadOnlyRoleName\x18\x05 \x01(\t\x12\"\n\x04meta\x18\x06 \x01(\x0b\x32\x14.google.protobuf.Any\"<\n\x17\x43reateDevBranchResponse\x12!\n\x19\x64\x65vBranchReadOnlyRoleName\x18\x01 \x01(\t\"9\n\x14\x44ropDevBranchCommand\x12!\n\x19\x64\x65vBranchReadOnlyRoleName\x18\x01 \x01(\tb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.project_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CREATEPROJECTCOMMAND_CREATEPROJECTBIGQUERYMETA'].fields_by_name['region']._loaded_options = None + _globals['_CREATEPROJECTCOMMAND_CREATEPROJECTBIGQUERYMETA'].fields_by_name['region']._serialized_options = b'\030\001' + _globals['_DROPPROJECTCOMMAND_DROPPROJECTBIGQUERYMETA'].fields_by_name['region']._loaded_options = None + _globals['_DROPPROJECTCOMMAND_DROPPROJECTBIGQUERYMETA'].fields_by_name['region']._serialized_options = b'\030\001' + _globals['_CREATEPROJECTCOMMAND']._serialized_start=90 + _globals['_CREATEPROJECTCOMMAND']._serialized_end=747 + _globals['_CREATEPROJECTCOMMAND_CREATEPROJECTTERADATAMETA']._serialized_start=315 + _globals['_CREATEPROJECTCOMMAND_CREATEPROJECTTERADATAMETA']._serialized_end=403 + _globals['_CREATEPROJECTCOMMAND_CREATEPROJECTBIGQUERYMETA']._serialized_start=405 + _globals['_CREATEPROJECTCOMMAND_CREATEPROJECTBIGQUERYMETA']._serialized_end=479 + _globals['_CREATEPROJECTCOMMAND_CREATEPROJECTSNOWFLAKEMETA']._serialized_start=482 + _globals['_CREATEPROJECTCOMMAND_CREATEPROJECTSNOWFLAKEMETA']._serialized_end=702 + _globals['_CREATEPROJECTCOMMAND_FILESTORAGETYPE']._serialized_start=704 + _globals['_CREATEPROJECTCOMMAND_FILESTORAGETYPE']._serialized_end=747 + _globals['_CREATEPROJECTRESPONSE']._serialized_start=750 + _globals['_CREATEPROJECTRESPONSE']._serialized_end=1004 + _globals['_CREATEPROJECTRESPONSE_CREATEPROJECTSNOWFLAKEMETA']._serialized_start=948 + _globals['_CREATEPROJECTRESPONSE_CREATEPROJECTSNOWFLAKEMETA']._serialized_end=1004 + _globals['_UPDATEPROJECTCOMMAND']._serialized_start=1006 + _globals['_UPDATEPROJECTCOMMAND']._serialized_end=1081 + _globals['_DROPPROJECTCOMMAND']._serialized_start=1084 + _globals['_DROPPROJECTCOMMAND']._serialized_end=1319 + _globals['_DROPPROJECTCOMMAND_DROPPROJECTBIGQUERYMETA']._serialized_start=1247 + _globals['_DROPPROJECTCOMMAND_DROPPROJECTBIGQUERYMETA']._serialized_end=1319 + _globals['_CREATEDEVBRANCHCOMMAND']._serialized_start=1322 + _globals['_CREATEDEVBRANCHCOMMAND']._serialized_end=1498 + _globals['_CREATEDEVBRANCHRESPONSE']._serialized_start=1500 + _globals['_CREATEDEVBRANCHRESPONSE']._serialized_end=1560 + _globals['_DROPDEVBRANCHCOMMAND']._serialized_start=1562 + _globals['_DROPDEVBRANCHCOMMAND']._serialized_end=1619 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/project_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/project_pb2_grpc.py new file mode 100644 index 000000000..4b5054c17 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/project_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/project_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/service_pb2.py b/packages/php-storage-driver-common/generated-py/proto/service_pb2.py new file mode 100644 index 000000000..f21f7d033 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/service_pb2.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/service.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/service.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from proto import common_pb2 as proto_dot_common__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13proto/service.proto\x12\x1dkeboola.storageDriver.service\x1a\x12proto/common.proto2\x8c\x01\n\x14StorageDriverService\x12t\n\x07\x45xecute\x12\x33.keboola.storageDriver.command.common.DriverRequest\x1a\x34.keboola.storageDriver.command.common.DriverResponseb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.service_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_STORAGEDRIVERSERVICE']._serialized_start=75 + _globals['_STORAGEDRIVERSERVICE']._serialized_end=215 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/service_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/service_pb2_grpc.py new file mode 100644 index 000000000..9e42b5926 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/service_pb2_grpc.py @@ -0,0 +1,107 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + +from proto import common_pb2 as proto_dot_common__pb2 + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/service_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) + + +class StorageDriverServiceStub(object): + """* + Unified storage driver service providing all backend operations + Supports both generic Execute() for backward compatibility and typed RPC methods + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.Execute = channel.unary_unary( + '/keboola.storageDriver.service.StorageDriverService/Execute', + request_serializer=proto_dot_common__pb2.DriverRequest.SerializeToString, + response_deserializer=proto_dot_common__pb2.DriverResponse.FromString, + _registered_method=True) + + +class StorageDriverServiceServicer(object): + """* + Unified storage driver service providing all backend operations + Supports both generic Execute() for backward compatibility and typed RPC methods + """ + + def Execute(self, request, context): + """Generic execute method using wrapper pattern (backward compatible) + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_StorageDriverServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'Execute': grpc.unary_unary_rpc_method_handler( + servicer.Execute, + request_deserializer=proto_dot_common__pb2.DriverRequest.FromString, + response_serializer=proto_dot_common__pb2.DriverResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'keboola.storageDriver.service.StorageDriverService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('keboola.storageDriver.service.StorageDriverService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class StorageDriverService(object): + """* + Unified storage driver service providing all backend operations + Supports both generic Execute() for backward compatibility and typed RPC methods + """ + + @staticmethod + def Execute(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/keboola.storageDriver.service.StorageDriverService/Execute', + proto_dot_common__pb2.DriverRequest.SerializeToString, + proto_dot_common__pb2.DriverResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/packages/php-storage-driver-common/generated-py/proto/table_pb2.py b/packages/php-storage-driver-common/generated-py/proto/table_pb2.py new file mode 100644 index 000000000..1f6d4416b --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/table_pb2.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/table.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/table.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from proto import info_pb2 as proto_dot_info__pb2 +from proto.backend import bigQuery_pb2 as proto_dot_backend_dot_bigQuery__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11proto/table.proto\x12#keboola.storageDriver.command.table\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x10proto/info.proto\x1a\x1cproto/backend/bigQuery.proto\"\xb2\x01\n\x11TableColumnShared\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x0e\n\x06length\x18\x03 \x01(\t\x12\x10\n\x08nullable\x18\x04 \x01(\x08\x12\x0f\n\x07\x64\x65\x66\x61ult\x18\x05 \x01(\t\x12\"\n\x04meta\x18\x06 \x01(\x0b\x32\x14.google.protobuf.Any\x1a*\n\x17TeradataTableColumnMeta\x12\x0f\n\x07isLatin\x18\x01 \x01(\x08\"\xf8\x03\n\x12\x43reateTableCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12G\n\x07\x63olumns\x18\x03 \x03(\x0b\x32\x36.keboola.storageDriver.command.table.TableColumnShared\x12\x18\n\x10primaryKeysNames\x18\x04 \x03(\t\x12\"\n\x04meta\x18\x05 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\x12\n\x10SynapseTableMeta\x1a\xa5\x02\n\x11\x42igQueryTableMeta\x12R\n\x10timePartitioning\x18\x01 \x01(\x0b\x32\x38.keboola.storageDriver.backend.bigQuery.TimePartitioning\x12T\n\x11rangePartitioning\x18\x02 \x01(\x0b\x32\x39.keboola.storageDriver.backend.bigQuery.RangePartitioning\x12\x1e\n\x16requirePartitionFilter\x18\x03 \x01(\x08\x12\x46\n\nclustering\x18\x04 \x01(\x0b\x32\x32.keboola.storageDriver.backend.bigQuery.Clustering\"M\n\x10\x44ropTableCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12\x18\n\x0cignoreErrors\x18\x03 \x01(\x08\x42\x02\x18\x01\"\x85\x01\n\x10\x41\x64\x64\x43olumnCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12P\n\x10\x63olumnDefinition\x18\x03 \x01(\x0b\x32\x36.keboola.storageDriver.command.table.TableColumnShared\"\xa3\x01\n\x12\x41lterColumnCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12P\n\x10\x64\x65siredDefiniton\x18\x03 \x01(\x0b\x32\x36.keboola.storageDriver.command.table.TableColumnShared\x12\x1a\n\x12\x61ttributesToUpdate\x18\x04 \x03(\t\"H\n\x11\x44ropColumnCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12\x12\n\ncolumnName\x18\x03 \x01(\t\"Q\n\x14\x41\x64\x64PrimaryKeyCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12\x18\n\x10primaryKeysNames\x18\x04 \x03(\t\"8\n\x15\x44ropPrimaryKeyCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\"\xf7\x01\n\x13PreviewTableCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12\x0f\n\x07\x63olumns\x18\x03 \x03(\t\x12V\n\x07orderBy\x18\x04 \x03(\x0b\x32\x45.keboola.storageDriver.command.table.ImportExportShared.ExportOrderBy\x12V\n\x07\x66ilters\x18\x05 \x01(\x0b\x32\x45.keboola.storageDriver.command.table.ImportExportShared.ExportFilters\"\xad\x02\n\x14PreviewTableResponse\x12\x0f\n\x07\x63olumns\x18\x01 \x03(\t\x12K\n\x04rows\x18\x02 \x03(\x0b\x32=.keboola.storageDriver.command.table.PreviewTableResponse.Row\x1a\xb6\x01\n\x03Row\x12U\n\x07\x63olumns\x18\x01 \x03(\x0b\x32\x44.keboola.storageDriver.command.table.PreviewTableResponse.Row.Column\x1aX\n\x06\x43olumn\x12\x12\n\ncolumnName\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x13\n\x0bisTruncated\x18\x03 \x01(\x08\"\xf1\x11\n\x12ImportExportShared\x1a\xac\x02\n\x10TableWhereFilter\x12\x13\n\x0b\x63olumnsName\x18\x01 \x01(\t\x12\x63\n\x08operator\x18\x02 \x01(\x0e\x32Q.keboola.storageDriver.command.table.ImportExportShared.TableWhereFilter.Operator\x12\x0e\n\x06values\x18\x03 \x03(\t\x12R\n\x08\x64\x61taType\x18\x04 \x01(\x0e\x32@.keboola.storageDriver.command.table.ImportExportShared.DataType\":\n\x08Operator\x12\x06\n\x02\x65q\x10\x00\x12\x06\n\x02ne\x10\x01\x12\x06\n\x02gt\x10\x02\x12\x06\n\x02ge\x10\x03\x12\x06\n\x02lt\x10\x04\x12\x06\n\x02le\x10\x05\x1a(\n\x05Table\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x1a\xb4\x06\n\rImportOptions\x12\x17\n\x0ftimestampColumn\x18\x01 \x01(\t\x12)\n!convertEmptyValuesToNullOnColumns\x18\x02 \x03(\t\x12\x64\n\nimportType\x18\x03 \x01(\x0e\x32P.keboola.storageDriver.command.table.ImportExportShared.ImportOptions.ImportType\x12\x1c\n\x14numberOfIgnoredLines\x18\x04 \x01(\x05\x12\x62\n\tdedupType\x18\x05 \x01(\x0e\x32O.keboola.storageDriver.command.table.ImportExportShared.ImportOptions.DedupType\x12\x19\n\x11\x64\x65\x64upColumnsNames\x18\x06 \x03(\t\x12l\n\x0eimportStrategy\x18\x07 \x01(\x0e\x32T.keboola.storageDriver.command.table.ImportExportShared.ImportOptions.ImportStrategy\x12\x64\n\ncreateMode\x18\x08 \x01(\x0e\x32P.keboola.storageDriver.command.table.ImportExportShared.ImportOptions.CreateMode\x12\x14\n\x0cimportAsNull\x18\t \x03(\t\"<\n\nImportType\x12\x08\n\x04\x46ULL\x10\x00\x12\x0f\n\x0bINCREMENTAL\x10\x01\x12\x08\n\x04VIEW\x10\x02\x12\t\n\x05\x43LONE\x10\x03\"Q\n\tDedupType\x12\x15\n\x11UPDATE_DUPLICATES\x10\x00\x12\x15\n\x11INSERT_DUPLICATES\x10\x01\x12\x16\n\x12\x46\x41IL_ON_DUPLICATES\x10\x02\":\n\x0eImportStrategy\x12\x10\n\x0cSTRING_TABLE\x10\x00\x12\x16\n\x12USER_DEFINED_TABLE\x10\x01\"%\n\nCreateMode\x12\n\n\x06\x43REATE\x10\x00\x12\x0b\n\x07REPLACE\x10\x01\x1a\xee\x01\n\rExportOptions\x12\x14\n\x0cisCompressed\x18\x01 \x01(\x08\x12\x17\n\x0f\x63olumnsToExport\x18\x02 \x03(\t\x12V\n\x07orderBy\x18\x03 \x03(\x0b\x32\x45.keboola.storageDriver.command.table.ImportExportShared.ExportOrderBy\x12V\n\x07\x66ilters\x18\x04 \x01(\x0b\x32\x45.keboola.storageDriver.command.table.ImportExportShared.ExportFilters\x1a\xc0\x01\n\rExportFilters\x12\r\n\x05limit\x18\x03 \x01(\x05\x12\x13\n\x0b\x63hangeSince\x18\x04 \x01(\t\x12\x13\n\x0b\x63hangeUntil\x18\x05 \x01(\t\x12\x16\n\x0e\x66ulltextSearch\x18\x06 \x01(\t\x12^\n\x0cwhereFilters\x18\x07 \x03(\x0b\x32H.keboola.storageDriver.command.table.ImportExportShared.TableWhereFilter\x1a\xef\x01\n\rExportOrderBy\x12\x12\n\ncolumnName\x18\x01 \x01(\t\x12Z\n\x05order\x18\x02 \x01(\x0e\x32K.keboola.storageDriver.command.table.ImportExportShared.ExportOrderBy.Order\x12R\n\x08\x64\x61taType\x18\x03 \x01(\x0e\x32@.keboola.storageDriver.command.table.ImportExportShared.DataType\"\x1a\n\x05Order\x12\x07\n\x03\x41SC\x10\x00\x12\x08\n\x04\x44\x45SC\x10\x01\x1aK\n\rS3Credentials\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x12\x0e\n\x06region\x18\x05 \x01(\t\x12\r\n\x05token\x18\x04 \x01(\t\x1aK\n\x0e\x41\x42SCredentials\x12\x13\n\x0b\x61\x63\x63ountName\x18\x01 \x01(\t\x12\x10\n\x08sasToken\x18\x02 \x01(\t\x12\x12\n\naccountKey\x18\x03 \x01(\t\x1a-\n\x0eGCSCredentials\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06secret\x18\x02 \x01(\t\x1a\x38\n\x08\x46ilePath\x12\x0c\n\x04root\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x10\n\x08\x66ileName\x18\x03 \x01(\t\"a\n\x08\x44\x61taType\x12\n\n\x06STRING\x10\x00\x12\x0b\n\x07INTEGER\x10\x01\x12\n\n\x06\x44OUBLE\x10\x02\x12\n\n\x06\x42IGINT\x10\x03\x12\x08\n\x04REAL\x10\x04\x12\x0b\n\x07\x44\x45\x43IMAL\x10\x05\x12\r\n\tTIMESTAMP\x10\x06\"(\n\x0c\x46ileProvider\x12\x06\n\x02S3\x10\x00\x12\x07\n\x03\x41\x42S\x10\x01\x12\x07\n\x03GCS\x10\x02\"\x15\n\nFileFormat\x12\x07\n\x03\x43SV\x10\x00\"\xb2\t\n\x1aTableImportFromFileCommand\x12Z\n\x0c\x66ileProvider\x18\x01 \x01(\x0e\x32\x44.keboola.storageDriver.command.table.ImportExportShared.FileProvider\x12V\n\nfileFormat\x18\x02 \x01(\x0e\x32\x42.keboola.storageDriver.command.table.ImportExportShared.FileFormat\x12/\n\x11\x66ormatTypeOptions\x18\x03 \x01(\x0b\x32\x14.google.protobuf.Any\x12R\n\x08\x66ilePath\x18\x04 \x01(\x0b\x32@.keboola.storageDriver.command.table.ImportExportShared.FilePath\x12-\n\x0f\x66ileCredentials\x18\x05 \x01(\x0b\x32\x14.google.protobuf.Any\x12R\n\x0b\x64\x65stination\x18\x06 \x01(\x0b\x32=.keboola.storageDriver.command.table.ImportExportShared.Table\x12\\\n\rimportOptions\x18\x07 \x01(\x0b\x32\x45.keboola.storageDriver.command.table.ImportExportShared.ImportOptions\x12\"\n\x04meta\x18\x08 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\xa1\x03\n\x0e\x43svTypeOptions\x12\x14\n\x0c\x63olumnsNames\x18\x01 \x03(\t\x12\x11\n\tdelimiter\x18\x02 \x01(\t\x12\x11\n\tenclosure\x18\x03 \x01(\t\x12\x11\n\tescapedBy\x18\x04 \x01(\t\x12m\n\nsourceType\x18\x05 \x01(\x0e\x32Y.keboola.storageDriver.command.table.TableImportFromFileCommand.CsvTypeOptions.SourceType\x12o\n\x0b\x63ompression\x18\x06 \x01(\x0e\x32Z.keboola.storageDriver.command.table.TableImportFromFileCommand.CsvTypeOptions.Compression\"=\n\nSourceType\x12\x0f\n\x0bSINGLE_FILE\x10\x00\x12\x0f\n\x0bSLICED_FILE\x10\x01\x12\r\n\tDIRECTORY\x10\x02\"!\n\x0b\x43ompression\x12\x08\n\x04NONE\x10\x00\x12\x08\n\x04GZIP\x10\x01\x1a\xb1\x01\n\x17TeradataTableImportMeta\x12|\n\rimportAdapter\x18\x01 \x01(\x0e\x32\x65.keboola.storageDriver.command.table.TableImportFromFileCommand.TeradataTableImportMeta.ImportAdapter\"\x18\n\rImportAdapter\x12\x07\n\x03TPT\x10\x00\"\xfc\x02\n\x13TableImportResponse\x12\x19\n\x11importedRowsCount\x18\x01 \x01(\x03\x12\x16\n\x0etableRowsCount\x18\x02 \x01(\x03\x12\x16\n\x0etableSizeBytes\x18\x03 \x01(\x03\x12N\n\x06timers\x18\x04 \x03(\x0b\x32>.keboola.storageDriver.command.table.TableImportResponse.Timer\x12\x17\n\x0fimportedColumns\x18\x05 \x03(\t\x12\"\n\x04meta\x18\x06 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\'\n\x05Timer\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08\x64uration\x18\x02 \x01(\t\x1a\x64\n\x17TeradataTableImportMeta\x12\x11\n\timportLog\x18\x01 \x01(\t\x12\x1a\n\x12\x65rrorTable1records\x18\x02 \x01(\t\x12\x1a\n\x12\x65rrorTable2records\x18\x03 \x01(\t\"\xb1\x05\n\x1bTableImportFromTableCommand\x12\x63\n\x06source\x18\x01 \x01(\x0b\x32S.keboola.storageDriver.command.table.TableImportFromTableCommand.SourceTableMapping\x12R\n\x0b\x64\x65stination\x18\x02 \x01(\x0b\x32=.keboola.storageDriver.command.table.ImportExportShared.Table\x12\\\n\rimportOptions\x18\x03 \x01(\x0b\x32\x45.keboola.storageDriver.command.table.ImportExportShared.ImportOptions\x1a\xfa\x02\n\x12SourceTableMapping\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12\x0f\n\x07seconds\x18\x03 \x01(\x03\x12^\n\x0cwhereFilters\x18\x04 \x03(\x0b\x32H.keboola.storageDriver.command.table.ImportExportShared.TableWhereFilter\x12\r\n\x05limit\x18\x05 \x01(\x03\x12y\n\x0e\x63olumnMappings\x18\x06 \x03(\x0b\x32\x61.keboola.storageDriver.command.table.TableImportFromTableCommand.SourceTableMapping.ColumnMapping\x1aH\n\rColumnMapping\x12\x18\n\x10sourceColumnName\x18\x01 \x01(\t\x12\x1d\n\x15\x64\x65stinationColumnName\x18\x02 \x01(\t\"\xd4\x05\n\x18TableExportToFileCommand\x12M\n\x06source\x18\x01 \x01(\x0b\x32=.keboola.storageDriver.command.table.ImportExportShared.Table\x12Z\n\x0c\x66ileProvider\x18\x02 \x01(\x0e\x32\x44.keboola.storageDriver.command.table.ImportExportShared.FileProvider\x12V\n\nfileFormat\x18\x03 \x01(\x0e\x32\x42.keboola.storageDriver.command.table.ImportExportShared.FileFormat\x12R\n\x08\x66ilePath\x18\x04 \x01(\x0b\x32@.keboola.storageDriver.command.table.ImportExportShared.FilePath\x12-\n\x0f\x66ileCredentials\x18\x05 \x01(\x0b\x32\x14.google.protobuf.Any\x12\\\n\rexportOptions\x18\x06 \x01(\x0b\x32\x45.keboola.storageDriver.command.table.ImportExportShared.ExportOptions\x12\"\n\x04meta\x18\x07 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\xaf\x01\n\x17TeradataTableExportMeta\x12z\n\rexportAdapter\x18\x01 \x01(\x0e\x32\x63.keboola.storageDriver.command.table.TableExportToFileCommand.TeradataTableExportMeta.ExportAdapter\"\x18\n\rExportAdapter\x12\x07\n\x03TPT\x10\x00\"]\n\x19TableExportToFileResponse\x12@\n\ttableInfo\x18\x01 \x01(\x0b\x32-.keboola.storageDriver.command.info.TableInfo\"\x9c\x04\n\x16\x44\x65leteTableRowsCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12\x13\n\x0b\x63hangeSince\x18\x03 \x01(\t\x12\x13\n\x0b\x63hangeUntil\x18\x04 \x01(\t\x12^\n\x0cwhereFilters\x18\x05 \x03(\x0b\x32H.keboola.storageDriver.command.table.ImportExportShared.TableWhereFilter\x12m\n\x14whereRefTableFilters\x18\x06 \x03(\x0b\x32O.keboola.storageDriver.command.table.DeleteTableRowsCommand.WhereRefTableFilter\x1a\xe7\x01\n\x13WhereRefTableFilter\x12\x0e\n\x06\x63olumn\x18\x01 \x01(\t\x12j\n\x08operator\x18\x03 \x01(\x0e\x32X.keboola.storageDriver.command.table.DeleteTableRowsCommand.WhereRefTableFilter.Operator\x12\x0f\n\x07refPath\x18\x04 \x03(\t\x12\x10\n\x08refTable\x18\x05 \x01(\t\x12\x11\n\trefColumn\x18\x06 \x01(\t\"\x1e\n\x08Operator\x12\x06\n\x02IN\x10\x00\x12\n\n\x06NOT_IN\x10\x01\"c\n\x17\x44\x65leteTableRowsResponse\x12\x18\n\x10\x64\x65letedRowsCount\x18\x01 \x01(\x03\x12\x16\n\x0etableRowsCount\x18\x02 \x01(\x03\x12\x16\n\x0etableSizeBytes\x18\x03 \x01(\x03\"\xaa\x02\n CreateTableFromTimeTravelCommand\x12h\n\x06source\x18\x01 \x01(\x0b\x32X.keboola.storageDriver.command.table.CreateTableFromTimeTravelCommand.SourceTableMapping\x12R\n\x0b\x64\x65stination\x18\x02 \x01(\x0b\x32=.keboola.storageDriver.command.table.ImportExportShared.Table\x12\x11\n\ttimestamp\x18\x03 \x01(\x03\x1a\x35\n\x12SourceTableMapping\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\"<\n\x19\x43reateProfileTableCommand\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\"\xd0\x01\n\x1a\x43reateProfileTableResponse\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12\x0f\n\x07profile\x18\x03 \x01(\t\x12W\n\x07\x63olumns\x18\x04 \x03(\x0b\x32\x46.keboola.storageDriver.command.table.CreateProfileTableResponse.Column\x1a\'\n\x06\x43olumn\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07profile\x18\x02 \x01(\tb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.table_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_DROPTABLECOMMAND'].fields_by_name['ignoreErrors']._loaded_options = None + _globals['_DROPTABLECOMMAND'].fields_by_name['ignoreErrors']._serialized_options = b'\030\001' + _globals['_TABLECOLUMNSHARED']._serialized_start=164 + _globals['_TABLECOLUMNSHARED']._serialized_end=342 + _globals['_TABLECOLUMNSHARED_TERADATATABLECOLUMNMETA']._serialized_start=300 + _globals['_TABLECOLUMNSHARED_TERADATATABLECOLUMNMETA']._serialized_end=342 + _globals['_CREATETABLECOMMAND']._serialized_start=345 + _globals['_CREATETABLECOMMAND']._serialized_end=849 + _globals['_CREATETABLECOMMAND_SYNAPSETABLEMETA']._serialized_start=535 + _globals['_CREATETABLECOMMAND_SYNAPSETABLEMETA']._serialized_end=553 + _globals['_CREATETABLECOMMAND_BIGQUERYTABLEMETA']._serialized_start=556 + _globals['_CREATETABLECOMMAND_BIGQUERYTABLEMETA']._serialized_end=849 + _globals['_DROPTABLECOMMAND']._serialized_start=851 + _globals['_DROPTABLECOMMAND']._serialized_end=928 + _globals['_ADDCOLUMNCOMMAND']._serialized_start=931 + _globals['_ADDCOLUMNCOMMAND']._serialized_end=1064 + _globals['_ALTERCOLUMNCOMMAND']._serialized_start=1067 + _globals['_ALTERCOLUMNCOMMAND']._serialized_end=1230 + _globals['_DROPCOLUMNCOMMAND']._serialized_start=1232 + _globals['_DROPCOLUMNCOMMAND']._serialized_end=1304 + _globals['_ADDPRIMARYKEYCOMMAND']._serialized_start=1306 + _globals['_ADDPRIMARYKEYCOMMAND']._serialized_end=1387 + _globals['_DROPPRIMARYKEYCOMMAND']._serialized_start=1389 + _globals['_DROPPRIMARYKEYCOMMAND']._serialized_end=1445 + _globals['_PREVIEWTABLECOMMAND']._serialized_start=1448 + _globals['_PREVIEWTABLECOMMAND']._serialized_end=1695 + _globals['_PREVIEWTABLERESPONSE']._serialized_start=1698 + _globals['_PREVIEWTABLERESPONSE']._serialized_end=1999 + _globals['_PREVIEWTABLERESPONSE_ROW']._serialized_start=1817 + _globals['_PREVIEWTABLERESPONSE_ROW']._serialized_end=1999 + _globals['_PREVIEWTABLERESPONSE_ROW_COLUMN']._serialized_start=1911 + _globals['_PREVIEWTABLERESPONSE_ROW_COLUMN']._serialized_end=1999 + _globals['_IMPORTEXPORTSHARED']._serialized_start=2002 + _globals['_IMPORTEXPORTSHARED']._serialized_end=4291 + _globals['_IMPORTEXPORTSHARED_TABLEWHEREFILTER']._serialized_start=2025 + _globals['_IMPORTEXPORTSHARED_TABLEWHEREFILTER']._serialized_end=2325 + _globals['_IMPORTEXPORTSHARED_TABLEWHEREFILTER_OPERATOR']._serialized_start=2267 + _globals['_IMPORTEXPORTSHARED_TABLEWHEREFILTER_OPERATOR']._serialized_end=2325 + _globals['_IMPORTEXPORTSHARED_TABLE']._serialized_start=2327 + _globals['_IMPORTEXPORTSHARED_TABLE']._serialized_end=2367 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS']._serialized_start=2370 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS']._serialized_end=3190 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS_IMPORTTYPE']._serialized_start=2948 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS_IMPORTTYPE']._serialized_end=3008 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS_DEDUPTYPE']._serialized_start=3010 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS_DEDUPTYPE']._serialized_end=3091 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS_IMPORTSTRATEGY']._serialized_start=3093 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS_IMPORTSTRATEGY']._serialized_end=3151 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS_CREATEMODE']._serialized_start=3153 + _globals['_IMPORTEXPORTSHARED_IMPORTOPTIONS_CREATEMODE']._serialized_end=3190 + _globals['_IMPORTEXPORTSHARED_EXPORTOPTIONS']._serialized_start=3193 + _globals['_IMPORTEXPORTSHARED_EXPORTOPTIONS']._serialized_end=3431 + _globals['_IMPORTEXPORTSHARED_EXPORTFILTERS']._serialized_start=3434 + _globals['_IMPORTEXPORTSHARED_EXPORTFILTERS']._serialized_end=3626 + _globals['_IMPORTEXPORTSHARED_EXPORTORDERBY']._serialized_start=3629 + _globals['_IMPORTEXPORTSHARED_EXPORTORDERBY']._serialized_end=3868 + _globals['_IMPORTEXPORTSHARED_EXPORTORDERBY_ORDER']._serialized_start=3842 + _globals['_IMPORTEXPORTSHARED_EXPORTORDERBY_ORDER']._serialized_end=3868 + _globals['_IMPORTEXPORTSHARED_S3CREDENTIALS']._serialized_start=3870 + _globals['_IMPORTEXPORTSHARED_S3CREDENTIALS']._serialized_end=3945 + _globals['_IMPORTEXPORTSHARED_ABSCREDENTIALS']._serialized_start=3947 + _globals['_IMPORTEXPORTSHARED_ABSCREDENTIALS']._serialized_end=4022 + _globals['_IMPORTEXPORTSHARED_GCSCREDENTIALS']._serialized_start=4024 + _globals['_IMPORTEXPORTSHARED_GCSCREDENTIALS']._serialized_end=4069 + _globals['_IMPORTEXPORTSHARED_FILEPATH']._serialized_start=4071 + _globals['_IMPORTEXPORTSHARED_FILEPATH']._serialized_end=4127 + _globals['_IMPORTEXPORTSHARED_DATATYPE']._serialized_start=4129 + _globals['_IMPORTEXPORTSHARED_DATATYPE']._serialized_end=4226 + _globals['_IMPORTEXPORTSHARED_FILEPROVIDER']._serialized_start=4228 + _globals['_IMPORTEXPORTSHARED_FILEPROVIDER']._serialized_end=4268 + _globals['_IMPORTEXPORTSHARED_FILEFORMAT']._serialized_start=4270 + _globals['_IMPORTEXPORTSHARED_FILEFORMAT']._serialized_end=4291 + _globals['_TABLEIMPORTFROMFILECOMMAND']._serialized_start=4294 + _globals['_TABLEIMPORTFROMFILECOMMAND']._serialized_end=5496 + _globals['_TABLEIMPORTFROMFILECOMMAND_CSVTYPEOPTIONS']._serialized_start=4899 + _globals['_TABLEIMPORTFROMFILECOMMAND_CSVTYPEOPTIONS']._serialized_end=5316 + _globals['_TABLEIMPORTFROMFILECOMMAND_CSVTYPEOPTIONS_SOURCETYPE']._serialized_start=5220 + _globals['_TABLEIMPORTFROMFILECOMMAND_CSVTYPEOPTIONS_SOURCETYPE']._serialized_end=5281 + _globals['_TABLEIMPORTFROMFILECOMMAND_CSVTYPEOPTIONS_COMPRESSION']._serialized_start=5283 + _globals['_TABLEIMPORTFROMFILECOMMAND_CSVTYPEOPTIONS_COMPRESSION']._serialized_end=5316 + _globals['_TABLEIMPORTFROMFILECOMMAND_TERADATATABLEIMPORTMETA']._serialized_start=5319 + _globals['_TABLEIMPORTFROMFILECOMMAND_TERADATATABLEIMPORTMETA']._serialized_end=5496 + _globals['_TABLEIMPORTFROMFILECOMMAND_TERADATATABLEIMPORTMETA_IMPORTADAPTER']._serialized_start=5472 + _globals['_TABLEIMPORTFROMFILECOMMAND_TERADATATABLEIMPORTMETA_IMPORTADAPTER']._serialized_end=5496 + _globals['_TABLEIMPORTRESPONSE']._serialized_start=5499 + _globals['_TABLEIMPORTRESPONSE']._serialized_end=5879 + _globals['_TABLEIMPORTRESPONSE_TIMER']._serialized_start=5738 + _globals['_TABLEIMPORTRESPONSE_TIMER']._serialized_end=5777 + _globals['_TABLEIMPORTRESPONSE_TERADATATABLEIMPORTMETA']._serialized_start=5779 + _globals['_TABLEIMPORTRESPONSE_TERADATATABLEIMPORTMETA']._serialized_end=5879 + _globals['_TABLEIMPORTFROMTABLECOMMAND']._serialized_start=5882 + _globals['_TABLEIMPORTFROMTABLECOMMAND']._serialized_end=6571 + _globals['_TABLEIMPORTFROMTABLECOMMAND_SOURCETABLEMAPPING']._serialized_start=6193 + _globals['_TABLEIMPORTFROMTABLECOMMAND_SOURCETABLEMAPPING']._serialized_end=6571 + _globals['_TABLEIMPORTFROMTABLECOMMAND_SOURCETABLEMAPPING_COLUMNMAPPING']._serialized_start=6499 + _globals['_TABLEIMPORTFROMTABLECOMMAND_SOURCETABLEMAPPING_COLUMNMAPPING']._serialized_end=6571 + _globals['_TABLEEXPORTTOFILECOMMAND']._serialized_start=6574 + _globals['_TABLEEXPORTTOFILECOMMAND']._serialized_end=7298 + _globals['_TABLEEXPORTTOFILECOMMAND_TERADATATABLEEXPORTMETA']._serialized_start=7123 + _globals['_TABLEEXPORTTOFILECOMMAND_TERADATATABLEEXPORTMETA']._serialized_end=7298 + _globals['_TABLEEXPORTTOFILECOMMAND_TERADATATABLEEXPORTMETA_EXPORTADAPTER']._serialized_start=7274 + _globals['_TABLEEXPORTTOFILECOMMAND_TERADATATABLEEXPORTMETA_EXPORTADAPTER']._serialized_end=7298 + _globals['_TABLEEXPORTTOFILERESPONSE']._serialized_start=7300 + _globals['_TABLEEXPORTTOFILERESPONSE']._serialized_end=7393 + _globals['_DELETETABLEROWSCOMMAND']._serialized_start=7396 + _globals['_DELETETABLEROWSCOMMAND']._serialized_end=7936 + _globals['_DELETETABLEROWSCOMMAND_WHEREREFTABLEFILTER']._serialized_start=7705 + _globals['_DELETETABLEROWSCOMMAND_WHEREREFTABLEFILTER']._serialized_end=7936 + _globals['_DELETETABLEROWSCOMMAND_WHEREREFTABLEFILTER_OPERATOR']._serialized_start=7906 + _globals['_DELETETABLEROWSCOMMAND_WHEREREFTABLEFILTER_OPERATOR']._serialized_end=7936 + _globals['_DELETETABLEROWSRESPONSE']._serialized_start=7938 + _globals['_DELETETABLEROWSRESPONSE']._serialized_end=8037 + _globals['_CREATETABLEFROMTIMETRAVELCOMMAND']._serialized_start=8040 + _globals['_CREATETABLEFROMTIMETRAVELCOMMAND']._serialized_end=8338 + _globals['_CREATETABLEFROMTIMETRAVELCOMMAND_SOURCETABLEMAPPING']._serialized_start=6193 + _globals['_CREATETABLEFROMTIMETRAVELCOMMAND_SOURCETABLEMAPPING']._serialized_end=6246 + _globals['_CREATEPROFILETABLECOMMAND']._serialized_start=8340 + _globals['_CREATEPROFILETABLECOMMAND']._serialized_end=8400 + _globals['_CREATEPROFILETABLERESPONSE']._serialized_start=8403 + _globals['_CREATEPROFILETABLERESPONSE']._serialized_end=8611 + _globals['_CREATEPROFILETABLERESPONSE_COLUMN']._serialized_start=8572 + _globals['_CREATEPROFILETABLERESPONSE_COLUMN']._serialized_end=8611 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/table_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/table_pb2_grpc.py new file mode 100644 index 000000000..110a641fb --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/table_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/table_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/proto/workspace_pb2.py b/packages/php-storage-driver-common/generated-py/proto/workspace_pb2.py new file mode 100644 index 000000000..9c727cff4 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/workspace_pb2.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: proto/workspace.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'proto/workspace.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from proto import table_pb2 as proto_dot_table__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15proto/workspace.proto\x12\'keboola.storageDriver.command.workspace\x1a\x19google/protobuf/any.proto\x1a\x11proto/table.proto\"\x93\x03\n\x16\x43reateWorkspaceCommand\x12\x13\n\x0bstackPrefix\x18\x01 \x01(\t\x12\x11\n\tprojectId\x18\x02 \x01(\t\x12\x13\n\x0bworkspaceId\x18\x03 \x01(\t\x12\x10\n\x08\x62ranchId\x18\x08 \x01(\t\x12\x17\n\x0fisBranchDefault\x18\t \x01(\x08\x12\x17\n\x0fprojectUserName\x18\x04 \x01(\t\x12\x17\n\x0fprojectRoleName\x18\x05 \x01(\t\x12\x1f\n\x17projectReadOnlyRoleName\x18\x06 \x01(\t\x12!\n\x19\x64\x65vBranchReadOnlyRoleName\x18\n \x01(\t\x12\"\n\x04meta\x18\x07 \x01(\x0b\x32\x14.google.protobuf.Any\x1a\x44\n\x1b\x43reateWorkspaceTeradataMeta\x12\x11\n\tpermSpace\x18\x01 \x01(\t\x12\x12\n\nspoolSpace\x18\x02 \x01(\t\x1a\x31\n\x1b\x43reateWorkspaceBigqueryMeta\x12\x12\n\x06region\x18\x01 \x01(\tB\x02\x18\x01\"\x87\x01\n\x17\x43reateWorkspaceResponse\x12\x19\n\x11workspaceUserName\x18\x01 \x01(\t\x12\x19\n\x11workspaceRoleName\x18\x02 \x01(\t\x12\x19\n\x11workspacePassword\x18\x03 \x01(\t\x12\x1b\n\x13workspaceObjectName\x18\x04 \x01(\t\"|\n\x14\x44ropWorkspaceCommand\x12\x19\n\x11workspaceUserName\x18\x01 \x01(\t\x12\x19\n\x11workspaceRoleName\x18\x02 \x01(\t\x12\x1b\n\x13workspaceObjectName\x18\x03 \x01(\t\x12\x11\n\tisCascade\x18\x04 \x01(\x08\"e\n\x15\x43learWorkspaceCommand\x12\x1b\n\x13workspaceObjectName\x18\x01 \x01(\t\x12\x14\n\x0cignoreErrors\x18\x02 \x01(\x08\x12\x19\n\x11objectsToPreserve\x18\x03 \x03(\t\":\n\x1dResetWorkspacePasswordCommand\x12\x19\n\x11workspaceUserName\x18\x01 \x01(\t\"V\n\x1eResetWorkspacePasswordResponse\x12\x19\n\x11workspaceUserName\x18\x01 \x01(\t\x12\x19\n\x11workspacePassword\x18\x02 \x01(\t\"n\n\x1a\x44ropWorkspaceObjectCommand\x12\x1b\n\x13workspaceObjectName\x18\x01 \x01(\t\x12\x18\n\x10objectNameToDrop\x18\x02 \x01(\t\x12\x19\n\x11ignoreIfNotExists\x18\x03 \x01(\x08\"\xab\x01\n$GrantWorkspaceAccessToProjectCommand\x12\x19\n\x11workspaceUserName\x18\x01 \x01(\t\x12\x19\n\x11workspaceRoleName\x18\x02 \x01(\t\x12\x1b\n\x13workspaceObjectName\x18\x03 \x01(\t\x12\x17\n\x0fprojectUserName\x18\x04 \x01(\t\x12\x17\n\x0fprojectRoleName\x18\x05 \x01(\t\"\xac\x01\n%RevokeWorkspaceAccessToProjectCommand\x12\x19\n\x11workspaceUserName\x18\x01 \x01(\t\x12\x19\n\x11workspaceRoleName\x18\x02 \x01(\t\x12\x1b\n\x13workspaceObjectName\x18\x03 \x01(\t\x12\x17\n\x0fprojectUserName\x18\x04 \x01(\t\x12\x17\n\x0fprojectRoleName\x18\x05 \x01(\t\"\xa8\x05\n\x1bLoadTableToWorkspaceCommand\x12g\n\x06source\x18\x01 \x01(\x0b\x32W.keboola.storageDriver.command.workspace.LoadTableToWorkspaceCommand.SourceTableMapping\x12R\n\x0b\x64\x65stination\x18\x02 \x01(\x0b\x32=.keboola.storageDriver.command.table.ImportExportShared.Table\x12\\\n\rimportOptions\x18\x03 \x01(\x0b\x32\x45.keboola.storageDriver.command.table.ImportExportShared.ImportOptions\x1a\xed\x02\n\x12SourceTableMapping\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x11\n\ttableName\x18\x02 \x01(\t\x12^\n\x0cwhereFilters\x18\x03 \x03(\x0b\x32H.keboola.storageDriver.command.table.ImportExportShared.TableWhereFilter\x12\r\n\x05limit\x18\x04 \x01(\x03\x12}\n\x0e\x63olumnMappings\x18\x05 \x03(\x0b\x32\x65.keboola.storageDriver.command.workspace.LoadTableToWorkspaceCommand.SourceTableMapping.ColumnMapping\x1aH\n\rColumnMapping\x12\x18\n\x10sourceColumnName\x18\x01 \x01(\t\x12\x1d\n\x15\x64\x65stinationColumnName\x18\x02 \x01(\tb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.workspace_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_CREATEWORKSPACECOMMAND_CREATEWORKSPACEBIGQUERYMETA'].fields_by_name['region']._loaded_options = None + _globals['_CREATEWORKSPACECOMMAND_CREATEWORKSPACEBIGQUERYMETA'].fields_by_name['region']._serialized_options = b'\030\001' + _globals['_CREATEWORKSPACECOMMAND']._serialized_start=113 + _globals['_CREATEWORKSPACECOMMAND']._serialized_end=516 + _globals['_CREATEWORKSPACECOMMAND_CREATEWORKSPACETERADATAMETA']._serialized_start=397 + _globals['_CREATEWORKSPACECOMMAND_CREATEWORKSPACETERADATAMETA']._serialized_end=465 + _globals['_CREATEWORKSPACECOMMAND_CREATEWORKSPACEBIGQUERYMETA']._serialized_start=467 + _globals['_CREATEWORKSPACECOMMAND_CREATEWORKSPACEBIGQUERYMETA']._serialized_end=516 + _globals['_CREATEWORKSPACERESPONSE']._serialized_start=519 + _globals['_CREATEWORKSPACERESPONSE']._serialized_end=654 + _globals['_DROPWORKSPACECOMMAND']._serialized_start=656 + _globals['_DROPWORKSPACECOMMAND']._serialized_end=780 + _globals['_CLEARWORKSPACECOMMAND']._serialized_start=782 + _globals['_CLEARWORKSPACECOMMAND']._serialized_end=883 + _globals['_RESETWORKSPACEPASSWORDCOMMAND']._serialized_start=885 + _globals['_RESETWORKSPACEPASSWORDCOMMAND']._serialized_end=943 + _globals['_RESETWORKSPACEPASSWORDRESPONSE']._serialized_start=945 + _globals['_RESETWORKSPACEPASSWORDRESPONSE']._serialized_end=1031 + _globals['_DROPWORKSPACEOBJECTCOMMAND']._serialized_start=1033 + _globals['_DROPWORKSPACEOBJECTCOMMAND']._serialized_end=1143 + _globals['_GRANTWORKSPACEACCESSTOPROJECTCOMMAND']._serialized_start=1146 + _globals['_GRANTWORKSPACEACCESSTOPROJECTCOMMAND']._serialized_end=1317 + _globals['_REVOKEWORKSPACEACCESSTOPROJECTCOMMAND']._serialized_start=1320 + _globals['_REVOKEWORKSPACEACCESSTOPROJECTCOMMAND']._serialized_end=1492 + _globals['_LOADTABLETOWORKSPACECOMMAND']._serialized_start=1495 + _globals['_LOADTABLETOWORKSPACECOMMAND']._serialized_end=2175 + _globals['_LOADTABLETOWORKSPACECOMMAND_SOURCETABLEMAPPING']._serialized_start=1810 + _globals['_LOADTABLETOWORKSPACECOMMAND_SOURCETABLEMAPPING']._serialized_end=2175 + _globals['_LOADTABLETOWORKSPACECOMMAND_SOURCETABLEMAPPING_COLUMNMAPPING']._serialized_start=2103 + _globals['_LOADTABLETOWORKSPACECOMMAND_SOURCETABLEMAPPING_COLUMNMAPPING']._serialized_end=2175 +# @@protoc_insertion_point(module_scope) diff --git a/packages/php-storage-driver-common/generated-py/proto/workspace_pb2_grpc.py b/packages/php-storage-driver-common/generated-py/proto/workspace_pb2_grpc.py new file mode 100644 index 000000000..e8eb99bcd --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/proto/workspace_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.76.0' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in proto/workspace_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) diff --git a/packages/php-storage-driver-common/generated-py/requirements-grpc.txt b/packages/php-storage-driver-common/generated-py/requirements-grpc.txt new file mode 100644 index 000000000..62f33d666 --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/requirements-grpc.txt @@ -0,0 +1,8 @@ +# Python Protocol Buffers Runtime Library +# Required for using the generated protobuf Python code +protobuf>=3.21.0,<5.0.0 + +# gRPC Runtime and Tools +# Required for running gRPC servers and clients +grpcio>=1.60.0 +grpcio-tools>=1.60.0 diff --git a/packages/php-storage-driver-common/generated-py/requirements.txt b/packages/php-storage-driver-common/generated-py/requirements.txt new file mode 100644 index 000000000..5de959b0b --- /dev/null +++ b/packages/php-storage-driver-common/generated-py/requirements.txt @@ -0,0 +1,3 @@ +# Python Protocol Buffers Runtime Library +# Required for using the generated protobuf Python code +protobuf>=3.21.0,<5.0.0 diff --git a/packages/php-storage-driver-common/generated/GPBMetadata/Proto/Service.php b/packages/php-storage-driver-common/generated/GPBMetadata/Proto/Service.php new file mode 100644 index 000000000..b7ec737c4 --- /dev/null +++ b/packages/php-storage-driver-common/generated/GPBMetadata/Proto/Service.php @@ -0,0 +1,29 @@ +internalAddGeneratedFile( + ' + +proto/service.protokeboola.storageDriver.service2 +StorageDriverServicet +Execute3.keboola.storageDriver.command.common.DriverRequest4.keboola.storageDriver.command.common.DriverResponsebproto3' + , true); + + static::$is_initialized = true; + } +} + diff --git a/packages/php-storage-driver-common/proto/service.proto b/packages/php-storage-driver-common/proto/service.proto new file mode 100644 index 000000000..78c5c231a --- /dev/null +++ b/packages/php-storage-driver-common/proto/service.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package keboola.storageDriver.service; + +// Import all command and response definitions +import "proto/common.proto"; + +/** + * Unified storage driver service providing all backend operations + * Supports both generic Execute() for backward compatibility and typed RPC methods + */ +service StorageDriverService { + // Generic execute method using wrapper pattern (backward compatible) + rpc Execute(keboola.storageDriver.command.common.DriverRequest) + returns (keboola.storageDriver.command.common.DriverResponse); +}