• Stars
    star
    207
  • Rank 189,096 (Top 4 %)
  • Language
    PHP
  • License
    Apache License 2.0
  • Created over 2 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The official SingleStore Laravel driver.

SingleStore Driver for Laravel

Latest Stable Version Total Downloads License PHP Version Require Github Actions status image

This repository contains the official SingleStoreDB Driver for Laravel. This driver wraps the official MySQL support in Laravel in order to make it work nicer with SingleStoreDB. Specifically, this driver provides the following advantages over vanilla Laravel MySQL support:

  • Extensions to Eloquent allowing specific SingleStoreDB features to be specified through the Eloquent api. See Migrations for supported features.
  • Integration tested against SingleStoreDB across a matrix of PHP and Laravel versions.
  • JSON column support
  • Other compatibility fixes in query generation

TOC

Install

You can install the package via composer:

composer require singlestoredb/singlestoredb-laravel

This package requires pdo_mysql to be installed. If you aren't sure check to see if pdo_mysql is listed when you run php -i.

Usage

To enable the driver, head to your config/database.php file and create a new entry for SingleStore in your connections, and update your default to point to that new connection:

[
    'default' => env('DB_CONNECTION', 'singlestore'),

    'connections' => [
        'singlestore' => [
            'driver' => 'singlestore',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST'),
            'port' => env('DB_PORT'),
            'database' => env('DB_DATABASE'),
            'username' => env('DB_USERNAME'),
            'password' => env('DB_PASSWORD'),
            'unix_socket' => env('DB_SOCKET'),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
                PDO::ATTR_EMULATE_PREPARES => true,
            ]) : [],
        ],
    ]
]

The SingleStore driver is an extension of the MySQL driver, so you could also just change your driver from mysql to singlestore.

In case you want to store failed jobs in SingleStore, then make sure you also set it as the database in your config/queue.php file. At which point, you may actually prefer to set DB_CONNECTION='singlestore' in your environment variables.

'failed' => [
    'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
    'database' => env('DB_CONNECTION', 'singlestore'),
    'table' => 'failed_jobs',
],

Issues connecting to SingleStore Managed Service

If you are encountering issues connecting to the SingleStore Managed Service, it may be due to your environment not being able to verify the SSL certificate used to secure connections. You can fix this by downloading and manually specifying the SingleStore certificate file.

  • Download the file here
  • In the Laravel SingleStore connection configuration, point the variable PDO::MYSQL_ATTR_SSL_CA at singlestore_bundle.pem:
'options' => extension_loaded('pdo_mysql') ? array_filter([
    PDO::MYSQL_ATTR_SSL_CA => 'path/to/singlestore_bundle.pem',
    PDO::ATTR_EMULATE_PREPARES => true,
]) : [],

Persistent Connections (performance optimization)

In general, we recommend enabling PDO::ATTR_PERSISTENT when connecting to SingleStoreDB. This is because opening new connections to SingleStoreDB is very expensive compared to running many transactional queries. By using PDO::ATTR_PERSISTENT, you can greatly improve the performance of transactional workloads.

The only downside to using persistent connections is that you need to ensure that transactions are correctly cleaned up as well as being careful when changing session variables or the context database. You can read more about this feature in the official documentation on php.net.

Also, note that SingleStoreDB in it's default configuration can handle very large numbers of idle connections with no performance impact. The default is roughly 100,000 idle connections per aggregator, but that can be set much higher if your server can handle it.

To enable this feature, simply update your options to include PDO::ATTR_PERSISTENT => true:

'options' => extension_loaded('pdo_mysql') ? array_filter([
    PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
    PDO::ATTR_EMULATE_PREPARES => true,
    PDO::ATTR_PERSISTENT => true,
]) : [],

PHP Versions before 8.1

In PHP versions before 8.1, the flag PDO::ATTR_EMULATE_PREPARES results in a bug by which all attributes returned by MySQL (and SingleStoreDB) are returned as strings.

For example, a table with a column named user_id and a type of int(10), if the row value is 5423 we would get a string like "5423" in PHP.

This is a historic and known bug:

The best method to solve this is to upgrade to PHP 8.1 or higher. If that's not possible, Eloquent's attribute casting is the next best solution.

Migrations

This driver provides many SingleStore specific methods for creating or modifying tables. They are listed below. For more information see the create table docs on SingleStore.

Universal Storage Tables (Columnstore)

By default, tables created by this driver will use SingleStoreDB Universal Storage. Universal Storage leverages both column and row oriented data structures to automatically optimize storage for transactional and analytical workloads. In general, you should use this table type for all tables unless you profile your workload and determine that another table type is better.

To create a table, you can simply use Schema::create:

Schema::create('table', function (Blueprint $table) {
    // ... column definitions, indexes, table options
});

Rowstore Tables

To create a rowstore table, use the rowstore method. Rowstore tables are optimized for low-latency transactional workloads with high concurrency at the expense of memory. In general, we recommend using Universal Storage (see above) and benchmarking your workload before using a rowstore table.

Schema::create('table', function (Blueprint $table) {
    $table->rowstore();

    // ...
});

Reference Tables

To create a reference table, you may use the reference method. Reference tables are fully replicated to every node in the cluster. This means that if you store 1000 rows in a reference table, those 1000 rows will be copied many times. Because of this you should only store small amounts of data in reference tables, and only when you need to reference that data via joins against non-collocated data in other tables. Inserts and updates to reference tables will also run slower due to the high replication overhead.

Schema::create('table', function (Blueprint $table) {
    $table->reference();

    // ...
});

Global Temporary Tables

To create a global temporary table, you may use the global method on the table.

Schema::create('table', function (Blueprint $table) {
    $table->rowstore();
    $table->temporary();
    $table->global();

    // ...
});

You may also use either of the following two methods:

// Fluent
$table->rowstore()->temporary()->global();

// As an argument to `temporary`.
$table->temporary($global = true);

Sparse Columns

You can mark particular columns as sparse fluently by appending sparse to the column's definition. This only applies to Rowstore tables.

Schema::create('table', function (Blueprint $table) {
    $table->rowstore();

    $table->string('name')->nullable()->sparse();
});

Sparse Tables

You can mark particular entire tables as sparse fluently by appending sparse to the column's definition. This only applies to Rowstore tables.

Schema::create('table', function (Blueprint $table) {
    $table->rowstore();

    $table->string('name');

    $table->sparse();
});

Shard Keys

You can add a shard key to your tables using the standalone shardKey method, or fluently by appending shardKey to the column definition.

Schema::create('table', function (Blueprint $table) {
    $table->string('name');

    $table->shardKey('name');
});

Schema::create('table', function (Blueprint $table) {
    $table->string('name')->shardKey();
});

Schema::create('table', function (Blueprint $table) {
    $table->string('f_name');
    $table->string('l_name');

    $table->shardKey(['f_name', 'l_name']);
});

Sort Keys

You can add a sort key to your tables using the standalone sortKey method, or fluently by appending sortKey to the column definition.

Schema::create('table', function (Blueprint $table) {
    $table->string('name');

    $table->sortKey('name');
});

Schema::create('table', function (Blueprint $table) {
    $table->string('name')->sortKey();
});

Schema::create('table', function (Blueprint $table) {
    $table->string('f_name');
    $table->string('l_name');

    $table->sortKey(['f_name', 'l_name']);
});

Sort keys sort in ascending order by default. If you would like to create a sort key which sorts descending you can set the key direction to desc.

Schema::create('table', function (Blueprint $table) {
    $table->string('name');

    $table->sortKey('name', 'desc');
});

Schema::create('table', function (Blueprint $table) {
    $table->string('name')->sortKey('desc');
});

You may also define the sort key direction per-column using the following syntax:

Schema::create('table', function (Blueprint $table) {
    $table->string('f_name');
    $table->string('l_name');

    $table->sortKey([['f_name', 'asc'], ['l_name', 'desc']]);
});

Sometimes you may want to tune columnstore per table. You can do it by appending with fluently to the sortKey definition.

Schema::create('table', function (Blueprint $table) {
    $table->string('name');

    $table->sortKey('name')->with(['columnstore_segment_rows' => 100000]);
});

Schema::create('table', function (Blueprint $table) {
    $table->string('name')->sortKey()->with(['columnstore_segment_rows' => 100000]);
});

However, you may want to tune it without setting a column as sort key. You can do that by creating an empty sortKey definition:

Schema::create('table', function (Blueprint $table) {
    $table->string('name');

    $table->sortKey()->with(['columnstore_segment_rows' => 100000]);
});

Unique Keys

You can add an unique key to your tables using the standalone unique method, or fluently by appending unique to the column definition.

Note
SingleStore requires that the shard key is contained within an unique key. This means that in most cases you can't use the fluent api as you will likely need to specify more than one column. This restriction does not apply to reference tables.

Schema::create('table', function (Blueprint $table) {
    $table->string('key');
    $table->string('val');

    $table->shardKey('key');
    $table->unique(['key', 'val']);
});

Schema::create('table', function (Blueprint $table) {
    $table->reference();
    $table->string('name')->unique();
});

Hash Keys

You can add a hash key to your tables using the third argument to the index function. Note that by default, indexes on Universal Storage Tables (Columnstore) are always hash indexes, so a simple .index(foo) is usually sufficient. On Rowstore tables this syntax is needed to create a hash index.

Schema::create('table', function (Blueprint $table) {
    $table->string('name');
    $table->index('name', 'name_idx', 'hash');
});

Series Timestamps

To denote a column as a series timestamp, use the seriesTimestamp column modifier.

Schema::create('table', function (Blueprint $table) {
    $table->datetime('created_at')->seriesTimestamp();

    // Or make it sparse
    $table->datetime('deleted_at')->nullable()->seriesTimestamp()->sparse();
});

Computed Columns

SingleStore does not support virtual computed columns. You must use Laravel's storedAs method to create a persisted computed column.

Schema::create('test', function (Blueprint $table) {
    $table->integer('a');
    $table->integer('b');
    $table->integer('c')->storedAs('a + b');
});

Increment Columns without Primary Key

Sometimes you may want to set a custom primary key. However if your table has an int increment column, Laravel, by default, always sets this column as the primary key. Even if you manually set another one. This behavior can be disabled using the withoutPrimaryKey method.

Schema::create('test', function (Blueprint $table) {
    $table->id()->withoutPrimaryKey();
    $table->uuid('uuid');
    
    $table->primary(['id',  'uuid']);
});

Full-text search using FULLTEXT indexes

SingleStoreDB supports full-text search across text columns in a columnstore table using the FULLTEXT index type.

Keep in mind that FULLTEXT is only supported when using the utf8_unicode_ci collation. An exception will be thrown if you try to add the index to a column with an unsupported collation.

Schema::create('test', function (Blueprint $table) {
    $table->id();
    $table->text('first_name')->collation('utf8_unicode_ci');

    $table->fullText(['first_name']);
});

Testing

Execute the tests using PHPUnit

./vendor/bin/phpunit

To test against an active SingleStore database, create a .env file and populate the following variables:

DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
DB_HOST=

Now when executing your tests, enable the integration tests by running

HYBRID_INTEGRATION=1 ./vendor/bin/phpunit

Compatibility matrix

Driver version Laravel version PHP version
0.0 - 1.4 8 7.3 - 8.0
9 8.0 - 8.1
1.5 8 7.3 - 8.0
9 8.0 - 8.1
10 8.1

License

This library is licensed under the Apache 2.0 License.

Resources

User agreement

SINGLESTORE, INC. ("SINGLESTORE") AGREES TO GRANT YOU AND YOUR COMPANY ACCESS TO THIS OPEN SOURCE SOFTWARE CONNECTOR ONLY IF (A) YOU AND YOUR COMPANY REPRESENT AND WARRANT THAT YOU, ON BEHALF OF YOUR COMPANY, HAVE THE AUTHORITY TO LEGALLY BIND YOUR COMPANY AND (B) YOU, ON BEHALF OF YOUR COMPANY ACCEPT AND AGREE TO BE BOUND BY ALL OF THE OPEN SOURCE TERMS AND CONDITIONS APPLICABLE TO THIS OPEN SOURCE CONNECTOR AS SET FORTH BELOW (THIS “AGREEMENT”), WHICH SHALL BE DEFINITIVELY EVIDENCED BY ANY ONE OF THE FOLLOWING MEANS: YOU, ON BEHALF OF YOUR COMPANY, CLICKING THE “DOWNLOAD, “ACCEPTANCE” OR “CONTINUE” BUTTON, AS APPLICABLE OR COMPANY’S INSTALLATION, ACCESS OR USE OF THE OPEN SOURCE CONNECTOR AND SHALL BE EFFECTIVE ON THE EARLIER OF THE DATE ON WHICH THE DOWNLOAD, ACCESS, COPY OR INSTALL OF THE CONNECTOR OR USE ANY SERVICES (INCLUDING ANY UPDATES OR UPGRADES) PROVIDED BY SINGLESTORE. BETA SOFTWARE CONNECTOR

Customer Understands and agrees that it is being granted access to pre-release or “beta” versions of SingleStore’s open source software connector (“Beta Software Connector”) for the limited purposes of non-production testing and evaluation of such Beta Software Connector. Customer acknowledges that SingleStore shall have no obligation to release a generally available version of such Beta Software Connector or to provide support or warranty for such versions of the Beta Software Connector for any production or non-evaluation use.

NOTWITHSTANDING ANYTHING TO THE CONTRARY IN ANY DOCUMENTATION, AGREEMENT OR IN ANY ORDER DOCUMENT, SINGLESTORE WILL HAVE NO WARRANTY, INDEMNITY, SUPPORT, OR SERVICE LEVEL, OBLIGATIONS WITH RESPECT TO THIS BETA SOFTWARE CONNECTOR (INCLUDING TOOLS AND UTILITIES).

APPLICABLE OPEN SOURCE LICENSE: Apache 2.0

IF YOU OR YOUR COMPANY DO NOT AGREE TO THESE TERMS AND CONDITIONS, DO NOT CHECK THE ACCEPTANCE BOX, AND DO NOT DOWNLOAD, ACCESS, COPY, INSTALL OR USE THE SOFTWARE OR THE SERVICES.

More Repositories

1

webinar-code-examples

Jupyter Notebook
139
star
2

python-wasi

Utilities for building CPython for the WASI platform
C
70
star
3

singlestoredb-samples

Find script examples that you can run out of the box in your SingleStoreDB.
Jupyter Notebook
57
star
4

wasi-data

WASI Data Proposal
46
star
5

singlestoredb-dev-image

The SingleStoreDB Dev Container is the fastest way to develop with SingleStore on your laptop or in a CI/CD environment.
Shell
41
star
6

wasix

POSIX compatibility layer for WASI builds
C
34
star
7

singlestore-logistics-sim

Scalable package delivery logistics simulator built using SingleStore and Vectorized Redpanda
Go
31
star
8

singlestore-kai-examples

TypeScript
26
star
9

spaces-notebooks

Collection of notebooks for use with SingleStoreDB
Jupyter Notebook
23
star
10

singlestoredb-python

Python SDK for the SingleStore database and workspace management APIs
Python
20
star
11

singlestore-wasm-toolkit

Tools to streamline development of Wasm UDFs for SingleStoreDB.
Rust
17
star
12

singlestore-workshop-data-intensive-app

This repo provides a starting point for building applications using SingleStore, Redpanda (by Vectorized), and the Go language. SingleStore is a scale-out relational database built for data-intensive workloads. Redpanda is a Kafka API compatible streaming platform for mission-critical workloads created by the team at Vectorized.
Go
16
star
13

wasm-space-program

A large scale simulation which pits millions of space ships against each other in a virtual universe all running directly in SingleStore.
TypeScript
12
star
14

terraform-provider-singlestoredb

Go
12
star
15

writ

A CLI tool for quickly spot-testing Wasm functions that have been compiled with WIT bindings.
Python
11
star
16

demo-realtime-digital-marketing

This application is a demo of how to use SingleStore to serve ads to users based on their behavior and realtime location.
TypeScript
9
star
17

elegance-sdk-app-book-query

TypeScript
8
star
18

Wasm-Day-2021-Distributed-Computation-with-WASM-and-WASI

7
star
19

esports-low-latency-analytics

Go
6
star
20

demo-sentiment-analysis

Jupyter Notebook
5
star
21

start-with-singlestore-go

Go
5
star
22

getting-started-with-singlestoredb

Take a quick tour of SingleStore, SQL Editor tool, and look at how to quickly ingest and query lots of data using SingleStore Pipelines.
5
star
23

wasi-data-python

Python utilities for implementing wasi-data modules and witx types for wasm modules.
Python
5
star
24

estore

TypeScript
5
star
25

gpt-database-query

Python
4
star
26

singlestoredb-fly

You can use this repo to quickly run SingleStoreDB on Fly.io
4
star
27

start-with-laravel

PHP
3
star
28

100-billion-rows

Dockerfile
3
star
29

start-with-singlestore-csharp

C#
3
star
30

key-value-store-demo

Whether you're using an ORM or straight SQL, you can get started with SingleStore (formerly MemSQL) fast. Here's an introductory sample of using SingleStore with Node and JavaScript. This sample includes all the CRUD methods: Create, Read by id, Read all, Update, and Delete.
JavaScript
3
star
31

to-wit

A C/C++ library for parsing Wasm WIT files
Rust
3
star
32

cdc-out-examples

Code examples for CDC out in SingleStore 8.5+
Python
3
star
33

http-client-js

SingleStore HTTP Client for JavaScript
JavaScript
2
star
34

s2kv

Go
2
star
35

timestamp9

Rust
2
star
36

flight-visualizer-serverless

Web app for visualizing all planes flying in the world in real-time or in the past, built with SingleStore and Cloudflare Workers
TypeScript
2
star
37

wasm-eval

A system for comparing available features and performance of WebAssembly runtimes.
Jupyter Notebook
2
star
38

ibis-singlestoredb

Ibis backend for SingleStore
Python
2
star
39

wasm-udf-tutorial

DevContainer and example code for the SingleStore Wasm UDF Tutorial
2
star
40

react-terminal-plus

TypeScript
2
star
41

elegance-sdk

TypeScript
2
star
42

elegance-sdk-app-books-chat

TypeScript
2
star
43

singlestore-wasm-demo

Demo early prototypes with WASM
Rust
2
star
44

http-client-generator

Client generator framework for SingleStore's HTTP API.
Shell
1
star
45

start-with-singlestore-python

Python
1
star
46

demo-wasm-youtube-sentiment

Sentiment analysis using SingleStore + Wasm on Youtube trending videos
Jupyter Notebook
1
star
47

sqlalchemy-singlestoredb

SQLAlchemy dialect for the SingleStore database
Python
1
star
48

start-with-singlestore-ruby

Ruby
1
star
49

start-with-singlestore-java

Java
1
star
50

singlestore-avro-sample

JavaScript
1
star
51

wasi-data-rust

Rust
1
star
52

devrel-notebook-examples

Jupyter Notebook
1
star
53

singlestoredb-minio

A sample of ingesting data from min.io into MemSQL
JavaScript
1
star
54

sqltools-singlestore-driver

TypeScript
1
star
55

gorm-singlestore

GORM database driver for SingleStore
Go
1
star
56

singlestore-planes-reference-architecture-node

TypeScript
1
star
57

vapor

Create and manage sessions for demo clusters.
Go
1
star
58

singlestore-cloudflare-external-functions

Example of how to use SingleStore External Functions with CloudFlare Workers
JavaScript
1
star
59

numeromancy

Rust
1
star
60

start-with-singlestore-node

JavaScript
1
star
61

pushwasm

Utility to push a Wasm UDF into SingleStoreDB
Rust
1
star
62

singlestoredb-statistics

Rust
1
star
63

singlestore

TypeScript
1
star
64

create-singlestoredb-app

This repo hosts the code for a tool to create a demo application powered by SingleStoreDB.
JavaScript
1
star
65

singlestoredb-extension-vector-ops

C
1
star
66

okql

Open-Source tools for KQL
Rust
1
star
67

demo-collocated-external-functions

This repo includes a standalone demonstration of using SingleStore external functions. External functions allow you to define a user defined function in SingleStore which, when executed, will call out to an externally defined web service.
Go
1
star
68

vector-dbs-ai-apps

Jupyter Notebook
1
star
69

genai-app-example

TypeScript
1
star
70

elegance-sdk-template-next

TypeScript
1
star
71

elegance-sdk-template-express

TypeScript
1
star