Create Wasm TVFs

Note

Creating Wasm TVFs is available as a preview-only feature in SingleStoreDB.

The following example creates a Wasm TVF (in Rust) that splits a string and returns the two sub-strings.

Setup VS Code

  1. Install the Remote - Containers extension in VS Code.

  2. Clone the wasm-udf-tutorial GitHub repository. This repository contains a VS Code Development Container with all the required dependencies.

    git clone git@github.com:singlestore-labs/wasm-udf-tutorial.git
  3. Open the Command Palette, and select Remote Containers: Open Folder in Container.

  4. Navigate to the directory where you cloned the GitHub repository, and select Open.

After VS Code completes building the project, proceed with the example. Unless specified otherwise, run all the commands in this container.

Create a Wasm TVF

  1. Open a new directory in VS Code, and initialize a Cargo package in this directory using the following command:

    cargo init --vcs none --lib
  2. Update the Cargo.toml file with the following configuration:

    [package]
    name = "split"
    version = "0.1.0"
    edition = "2018"
    
    [dependencies]
    wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen.git" }
    
    [lib]
    crate-type = ["cdylib"]
  3. Create a .wit file with the WIT specification, for example split.wit.

    record subphrase {
      str: string,
      idx: s32
    }
    split-str: func(phrase: string, delim: string) -> list<subphrase>
  4. Add the following code to the src/lib.rs file:

    wit_bindgen_rust::export!("split.wit");
    struct Split;
    use crate::split::Subphrase;
    
    impl split::Split for Split {
    
        fn split_str(phrase: String, delim: String) -> Vec<Subphrase> {
            phrase
                .split(&delim)
                .scan(0, |idx, s| {
                    let current = Subphrase {
                        str: s.to_string(),
                        idx: *idx as i32
                    };
                    *idx += (s.len() + delim.len()) as i32;
                    Some(current)
                })
                .collect()
        }
    }
  5. Compile the program into a Wasm module using the following command:

    cargo build --target wasm32-unknown-unknown

    The split.wasm file is created in the target/wasm32-unknown-unknown/debug/ directory.

  6. Upload the split.wasm and split.wit files to your cloud storage account, say an S3 bucket named wasm-modules.

Load the Wasm TVF

Execute the following command in the SingleStore command line:

CREATE DATABASE wasm_tutorial;
USE wasm_tutorial;
CREATE FUNCTION split_str RETURNS TABLE AS WASM FROM S3 'wasm-modules/split.wasm' 
        CREDENTIALS '{
                "aws_access_key_id": "ASIAZPIKLSJ3HM7FKAUB", 
                "aws_secret_access_key": FwoGZXIvYXdzEL3fv [...]"
        }' 
        CONFIG '{"region": "us-east-1"}'
WITH WIT FROM S3 'wasm-modules/split.wit'
        CREDENTIALS '{
                "aws_access_key_id": "ASIAZPIKLSJ3HM7FKAUB", 
                "aws_secret_access_key": FwoGZXIvYXdzEL3fv [...]"
        }' 
        CONFIG '{"region": "us-east-1"}';

This command imports the split.wit and split.wasm files created earlier in this example. The Wasm TVF is now ready to use. For example,

SELECT * FROM split_str('wasm_rocks_the_house', '_');
****
+-------+-----+
| str   | idx |
+-------+-----+
| wasm  |   0 |
| rocks |   5 |
| the   |  11 |
| house |  15 |
+-------+-----+

For more examples on using Wasm TVFs, see Wasm TVF example.