### Configure Snowflex Ecto Adapter Source: https://github.com/pepsico-ecommerce/snowflex/blob/master/README.md Configuration example for the Snowflex Ecto adapter in an Elixir application. It shows how to set up the adapter, specify transport, and provide authentication details like account name, username, and private key. ```elixir config :my_app, MyApp.Repo, adapter: Snowflex, transport: Snowflex.Transport.Http, # Optional, defaults to Http # Additional options passed to the transport account_name: "your-account", username: "your_username", private_key_path: "path/to/key.pem", # Path to private key file # OR alternatively, provide the private key as a string: # private_key_from_string: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----", public_key_fingerprint: "your_fingerprint" ``` -------------------------------- ### Snowflex Error Logging Metadata Source: https://github.com/pepsico-ecommerce/snowflex/blob/master/README.md Illustrates how Snowflex enriches error logs with contextual metadata for easier debugging. Includes examples of available metadata keys and how they appear in logs. ```elixir # Example Error Log snowflex_account_name=my_account snowflex_username=my_user snowflex_warehouse=MY_WH snowflex_database=MY_DB snowflex_statement=SELECT * FROM users [error] Snowflake query failed: [529] "Server too busy. Please retry." ``` -------------------------------- ### Stream Large Result Sets Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Provides examples for memory-efficient processing of large datasets using Repo.stream, including batch chunking. ```elixir MyApp.Repo.transaction(fn -> from(u in MyApp.User, where: u.age > 21) |> MyApp.Repo.stream() |> Stream.each(fn user -> IO.puts("Processing user: #{user.name}") end) |> Stream.run() end) MyApp.Repo.transaction(fn -> from(u in MyApp.User) |> MyApp.Repo.stream() |> Stream.chunk_every(100) |> Stream.each(fn batch -> Enum.each(batch, &process_user/1) end) |> Stream.run() end) ``` -------------------------------- ### Implement Custom Snowflex Mock Transport Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Provides an implementation of the Snowflex.Transport behaviour for creating a mock transport. This is useful for testing purposes or for simulating alternative communication methods without connecting to a live Snowflake instance. It defines functions for starting, executing statements, declaring, fetching, disconnecting, deallocating, and pinging. ```elixir defmodule MyApp.MockTransport do @behaviour Snowflex.Transport alias Snowflex.Result @impl true def start_link(_opts) do Agent.start_link(fn -> %{} end) end @impl true def execute_statement(_pid, statement, _params, _opts) do # Return mock results based on statement case statement do "SELECT 1" -> {:ok, %Result{columns: ["1"], rows: [[1]], num_rows: 1}} _ -> {:ok, %Result{columns: [], rows: [], num_rows: 0}} end end @impl true def declare(_pid, _statement, _params, _opts), do: {:ok, 0} @impl true def fetch(_pid, _cursor, _opts), do: {:halt, %Result{}} @impl true def disconnect(_pid), do: :ok @impl true def deallocate(_pid), do: :ok @impl true def ping(_pid), do: {:ok, %Result{}} end # Use in test config config :my_app, MyApp.Repo, adapter: Snowflex, transport: MyApp.MockTransport, account_name: "test", username: "test", public_key_fingerprint: "test" ``` -------------------------------- ### Execute Raw SQL Queries Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Shows how to run raw SQL queries using Repo.query, including parameter binding and accessing result metadata. ```elixir {:ok, result} = MyApp.Repo.query("SELECT * FROM users WHERE age > ?", [21]) {:ok, result} = MyApp.Repo.query( "SELECT COUNT(*) as total FROM users WHERE created_at > ?", [~U[2024-01-01 00:00:00Z]] ) ``` -------------------------------- ### Configure Private Key via String Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Demonstrates how to provide the Snowflake private key as a string directly in the configuration, which is useful for environment variables or secret management. ```elixir config :my_app, MyApp.Repo, adapter: Snowflex, account_name: "my-org-my-account", username: "my_user", private_key_from_string: System.get_env("SNOWFLAKE_PRIVATE_KEY") || """ -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC... -----END PRIVATE KEY----- """, public_key_fingerprint: "SHA256:abc123...", database: "MY_DB", schema: "MY_SCHEMA", warehouse: "MY_WH" ``` -------------------------------- ### Configure Req HTTP Client Options for Snowflex Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Demonstrates how to configure underlying HTTP client options for Snowflex using the Req library. This includes programmatically obtaining default options, modifying them (e.g., for custom Finch pools), and setting them via application configuration. It also shows how to specify connection options like timeouts and protocols, and how to use `req_options` for testing with plugs like `Req.Test`. ```elixir # Get Req options programmatically {:ok, options} = Snowflex.Transport.Http.options( account_name: "my-account", username: "my_user", private_key_path: "/path/to/key.pem", public_key_fingerprint: "SHA256:abc..." ) # Modify options for custom Finch pool custom_options = options |> Keyword.delete(:connect_options) |> Keyword.put(:finch, MyApp.CustomFinch) # Create custom Req client custom_client = Req.new(custom_options) # Configuration with connect_options config :my_app, MyApp.Repo, adapter: Snowflex, account_name: "my-account", username: "my_user", private_key_path: "/path/to/key.pem", public_key_fingerprint: "SHA256:abc...", connect_options: [ timeout: 30_000, protocols: [:http2] ], req_options: [ plug: {Req.Test, MyApp.SnowflakeStub} # For testing ] ``` -------------------------------- ### Configure Snowflex Ecto Repository Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Sets up the Ecto repository with Snowflex adapter settings including authentication, database connection details, and retry logic. ```elixir config :my_app, MyApp.Repo, adapter: Snowflex, transport: Snowflex.Transport.Http, account_name: "my-org-my-account", username: "my_user", private_key_path: "/path/to/key.pem", public_key_fingerprint: "SHA256:abc123...", database: "MY_DB", schema: "MY_SCHEMA", warehouse: "MY_WH", role: "MY_ROLE", timeout: :timer.seconds(30), token_lifetime: :timer.minutes(15), max_retries: 3, retry_base_delay: :timer.seconds(1), retry_max_delay: :timer.seconds(8) defmodule MyApp.Repo do use Ecto.Repo, otp_app: :my_app, adapter: Snowflex end ``` -------------------------------- ### Implement Snowflake Ecto Adapter Migration Helper Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt This snippet demonstrates how to create a wrapper module for the Snowflex Ecto adapter to maintain backward compatibility with legacy ODBC query patterns. It includes helper functions for raw SQL execution and result processing to map Snowflake result sets into standard Elixir maps. ```elixir defmodule MyApp.Snowflake do use Ecto.Repo, otp_app: :my_app, adapter: Snowflex def sql_query(query) do execute(query) end def param_query(query, params \\ %{}) do execute(query, params) end defp execute(query, params \\ %{}) do query |> query_many!(params) |> process_results() |> unwrap_single_result() end defp process_results([]), do: [] defp process_results([%Snowflex.Result{} = result | rest]) do [unpack_snowflex_result(result) | process_results(rest)] end defp process_results([other | rest]), do: [other | process_results(rest)] defp unpack_snowflex_result(%{columns: nil, num_rows: num_rows}), do: {:updated, num_rows} defp unpack_snowflex_result(%{columns: columns, rows: rows}) when is_list(columns) and is_list(rows) do headers = Enum.map(columns, &(to_string(&1) |> String.downcase())) Enum.map(rows, fn row -> Enum.zip(headers, row) |> Map.new() end) end defp unwrap_single_result([result]), do: result defp unwrap_single_result(results), do: results end MyApp.Snowflake.sql_query("SELECT * FROM users") MyApp.Snowflake.param_query("SELECT * FROM users WHERE id = ?", ["123"]) ``` -------------------------------- ### Generate Snowflex Migrations for Local PostgreSQL Testing Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Implements a custom Ecto Repo module that conditionally uses the Snowflex adapter or the Ecto.Adapters.Postgres adapter based on a configuration flag. It includes a `generate_migrations` function that leverages Snowflex.MigrationGenerator to create migrations for testing Snowflake schemas against a local PostgreSQL database. ```elixir # lib/my_app/repo.ex defmodule MyApp.Repo do defmacro __using__(_opts) do [select_repo(__CALLER__.module), add_schema_helper()] end defp select_repo(caller_mod) do config = Application.get_env(:my_app, caller_mod) if config[:use_local_db?] do quote do use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres alias Snowflex.MigrationGenerator require Snowflex.MigrationGenerator @spec generate_migrations(list(module())) :: :ok def generate_migrations(modules) do MigrationGenerator.generate_migrations(__MODULE__, modules) end end else quote do use Ecto.Repo, otp_app: :my_app, adapter: Snowflex end end end defp add_schema_helper do quote do def connection_value(key, default \ nil) do :my_app |> Application.get_env(__MODULE__, []) |> Keyword.get(key, default) end end end end # test/test_helper.exs MyApp.Repo.generate_migrations([ MyApp.User, MyApp.Post, {MyApp.CustomTable, {"SCHEMA.TABLE_NAME", [id: :string, name: :string], []}} ]) ``` -------------------------------- ### Execute Multiple SQL Statements Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Demonstrates running multiple SQL statements in a single request using Repo.query and Repo.query_many. ```elixir {:ok, results} = MyApp.Repo.query(""" CREATE TEMPORARY TABLE temp_users AS SELECT * FROM users WHERE age > 21; SELECT COUNT(*) FROM temp_users; SELECT * FROM temp_users LIMIT 5; """) {:ok, results} = MyApp.Repo.query_many("SELECT 1; SELECT 2; SELECT 3;") ``` -------------------------------- ### Configure Snowflake Repository with Ecto Source: https://github.com/pepsico-ecommerce/snowflex/blob/master/README.md Shows how to define a custom Ecto repository module for Snowflake, including helper functions for executing queries and processing result sets into maps. ```elixir defmodule MyApp.Snowflake do use Ecto.Repo, otp_app: :my_app, adapter: Snowflex def sql_query(query) do execute(query) end def param_query(query, params \\ %{}) do execute(query, params) end defp execute(query, params \\ %{}) do query |> query_many!(params) |> process_results() |> unwrap_single_result() end defp process_results([]), do: [] defp process_results([%Snowflex.Result{} = result | rest]), do: [unpack_snowflex_result(result) | process_results(rest)] defp process_results([other | rest]), do: [other | process_results(rest)] defp unpack_snowflex_result(%{columns: nil, num_rows: num_rows}), do: {:updated, num_rows} defp unpack_snowflex_result(%{columns: columns, rows: rows}) when is_list(columns) and is_list(rows) do headers = Enum.map(columns, &(to_string(&1) |> String.downcase())) rows |> Enum.map(fn row -> Enum.zip(headers, row) |> Map.new() end) end defp unwrap_single_result([result]), do: result defp unwrap_single_result(results), do: results end ``` -------------------------------- ### Perform Bulk Updates with Ecto Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Demonstrates how to perform bulk updates on records using Ecto.Repo.update_all, including conditional updates and incrementing values. ```elixir {count, nil} = MyApp.Repo.update_all( from(u in MyApp.User, where: u.age < 18), set: [age: 18] ) {count, nil} = MyApp.Repo.update_all( from(u in MyApp.User, where: u.id == ^"abc-123"), inc: [age: 1] ) ``` -------------------------------- ### Insert Records into Snowflake Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Demonstrates inserting single records using changesets and batch inserting multiple records using insert_all. ```elixir changeset = %MyApp.User{} |> Ecto.Changeset.cast(%{ id: Ecto.UUID.generate(), name: "Bob", email: "bob@example.com", age: 25, balance: Decimal.new("100.50"), created_at: DateTime.utc_now() }, [:id, :name, :email, :age, :balance, :created_at]) {:ok, user} = MyApp.Repo.insert(changeset) users_data = [ %{id: Ecto.UUID.generate(), name: "User 1", email: "u1@example.com", age: 20}, %{id: Ecto.UUID.generate(), name: "User 2", email: "u2@example.com", age: 22}, %{id: Ecto.UUID.generate(), name: "User 3", email: "u3@example.com", age: 24} ] {count, nil} = MyApp.Repo.insert_all(MyApp.User, users_data) ``` -------------------------------- ### Tag Queries for Observability Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Explains how to add query_tag metadata to Ecto operations to improve tracking and debugging in Snowflake. ```elixir users = MyApp.Repo.all(from(u in MyApp.User, where: u.age > 21), query_tag: "user_dashboard_query") {:ok, result} = MyApp.Repo.query("SELECT * FROM orders WHERE status = ?", ["pending"], query_tag: request_id) {:ok, user} = MyApp.Repo.insert(changeset, query_tag: "user_registration_flow") ``` -------------------------------- ### Execute Multiple Statements in Snowflex Source: https://github.com/pepsico-ecommerce/snowflex/blob/master/README.md Demonstrates how to execute multiple SQL statements in a single query request using Snowflex, which returns an array of results for each statement. ```elixir iex> Repo.query("SELECT 1; SELECT 2;") {:ok, [ %Snowflex.Result{rows: [[1]]}, %Snowflex.Result{rows: [[2]]} ] } ``` -------------------------------- ### Execute Deletion Operations Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Covers single record deletion using Repo.delete and bulk deletion using Repo.delete_all with conditional queries. ```elixir user = MyApp.Repo.get!(MyApp.User, "abc-123") {:ok, deleted_user} = MyApp.Repo.delete(user) {count, nil} = MyApp.Repo.delete_all( from(u in MyApp.User, where: u.created_at < ^~U[2020-01-01 00:00:00Z]) ) {count, nil} = MyApp.Repo.delete_all(MyApp.User) ``` -------------------------------- ### SQL Query Execution Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Executes a raw SQL query against the Snowflake database using the legacy-compatible interface. ```APIDOC ## POST /sql_query ### Description Executes a raw SQL string against the Snowflake data warehouse and returns processed results. ### Method POST ### Parameters #### Request Body - **query** (string) - Required - The raw SQL statement to execute. ### Request Example { "query": "SELECT * FROM users" } ### Response #### Success Response (200) - **result** (list/map) - The processed result set from Snowflake. #### Response Example [ {"id": "123", "name": "John Doe"} ] ``` -------------------------------- ### Tag Snowflex Ecto Queries Source: https://github.com/pepsico-ecommerce/snowflex/blob/master/README.md Demonstrates how to tag Ecto queries for improved observability in Snowflake. Tags can be custom identifiers or generated UUIDs, aiding in tracking query origins and debugging. ```elixir # Tag a query with a UUID MyRepo.all(query, query_tag: Ecto.UUID.generate()) # Tag a query with a custom identifier iex> MyRepo.insert(changeset, query_tag: "user_registration_abc") ``` -------------------------------- ### Handle Database Errors Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Demonstrates pattern matching on Snowflex.Error structs and handling Ecto changeset errors for robust application stability. ```elixir case MyApp.Repo.query("SELECT * FROM nonexistent_table") do {:ok, result} -> IO.inspect(result.rows) {:error, %Snowflex.Error{} = error} -> IO.puts("Error: #{error.message}") end try do MyApp.Repo.query!("INVALID SQL SYNTAX") rescue e in Snowflex.Error -> Logger.error("Query failed: #{e.message}") end ``` -------------------------------- ### Configure Snowflex Logger Metadata Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Configures the logger to include specific metadata related to Snowflex queries, such as account name, username, query ID, and statement details. This helps in debugging and tracing Snowflake operations. ```elixir config :logger, :console, format: "$time $metadata[$level] $message\n", metadata: [ :snowflex_account_name, :snowflex_username, :snowflex_query_id, :snowflex_statement, :snowflex_warehouse, :snowflex_role, :snowflex_database, :snowflex_schema ] ``` -------------------------------- ### Define Ecto Schemas for Snowflake Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Shows how to map Elixir modules to Snowflake tables using Ecto schema definitions with appropriate field types. ```elixir defmodule MyApp.User do use Ecto.Schema @primary_key {:id, :string, []} schema "users" do field :name, :string field :email, :string field :age, :integer field :balance, :decimal field :created_at, :utc_datetime field :metadata, :map end end defmodule MyApp.Post do use Ecto.Schema @primary_key {:id, :binary_id, autogenerate: true} schema "posts" do field :title, :string field :body, :string field :published_at, :naive_datetime belongs_to :user, MyApp.User, type: :string end end ``` -------------------------------- ### Query Data with Ecto Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Executes SELECT queries using Ecto query syntax, including support for filters, joins, aggregations, and pagination. ```elixir import Ecto.Query users = MyApp.Repo.all(from u in MyApp.User, where: u.age > 21) query = from u in MyApp.User, join: p in MyApp.Post, on: p.user_id == u.id, where: u.created_at > ^~U[2024-01-01 00:00:00Z], group_by: u.id, select: %{user_id: u.id, name: u.name, post_count: count(p.id)} results = MyApp.Repo.all(query) recent_users = MyApp.Repo.all( from u in MyApp.User, order_by: [desc: u.created_at], limit: 10, offset: 20 ) ``` -------------------------------- ### Parameterized Query Execution Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Executes a SQL query with parameters to prevent injection and handle dynamic inputs. ```APIDOC ## POST /param_query ### Description Executes a parameterized SQL query to safely handle dynamic values. ### Method POST ### Parameters #### Request Body - **query** (string) - Required - The SQL statement with placeholders. - **params** (list) - Required - The parameters to bind to the query. ### Request Example { "query": "SELECT * FROM users WHERE id = ?", "params": ["123"] } ### Response #### Success Response (200) - **result** (map) - The single result record matching the criteria. #### Response Example { "id": "123", "name": "John Doe" } ``` -------------------------------- ### Update Records in Snowflake Source: https://context7.com/pepsico-ecommerce/snowflex/llms.txt Updates existing records using Ecto changesets for single record updates. ```elixir import Ecto.Query user = MyApp.Repo.get!(MyApp.User, "abc-123") changeset = Ecto.Changeset.change(user, %{name: "Robert", age: 26}) {:ok, updated_user} = MyApp.Repo.update(changeset) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.