Giter VIP home page Giter VIP logo

simplesql's Introduction

Simple SQL

A no-frills SQL library for Scala 3.

SimpleSQL is a very thin wrapper around JDBC, which allows you to take full advantage of full SQL and any database with a JDBC driver.

SimpleSQL is not a functional DSL to build SQL queries (I recommend Quill for that, which unfortunately is not yet available for Scala 3), but it does offer safe string interpolation and utilities to work with product types, wich are the natural representation of relational data sets.

SimpleSQL has no dependencies. It is published to maven central, under io.crashbox:simplesql_3, but it can also be embedded by copying the file simplesql/src/package.scala into your application!

Example

import simplesql as sq

// a plain DataSource is needed, this example uses a connection pool implemented
// by HicariCP, but you are free to use whatever DataSource you wish
val ds: javax.sql.DataSource = {
  val ds = com.zaxxer.hikari.HikariDataSource()
  ds.setJdbcUrl("jdbc:sqlite::memory:")
  ds
}

// all queries must be run within the context of a connection, use either
// `sq.run` or `sq.transaction` blocks
sq.transaction(ds){

  sq.write(
    sql"""
      create table user (
        id integer primary key,
        name string not null,
        email string not null
      )
    """
  )

  sq.read[(Int, String, String)](sql"select * from user")
  sq.write(sql"""insert into user values (1, "admin", "[email protected]")""")

  case class User(id: Int, name: String, email: String) derives sq.Reader
  sq.read[User](sql"select * from user")
}

Explanation

Database connection

All queries must be run on a connection to a database. SimpleSQL models this through a Connection class, which is just a simple wrapper around java.sql.Connection.

A connection may be obtained as a context function through either simplesql.run or simplesql.transaction. Both functions provide a connection, however the latter will automatically roll back any changes, should an exception be thrown in its body.

An in-scope connection also gives access to the sql string intepolator. This interpolator is a utility to build simplesql.Querys, which are builders for java.sql.PreparedStatements. In other words, it can be used to build injection-safe queries with interpolated parameters. Interpolated parameters must be primitve types (supported by JDBC).

Read Queries

Read queries (e.g. selects) must be run in a read call. A read must have its result type specified. The result type may be any primitive type supported by JDBC ResultSets or a product thereof (including named products, i.e. case classes). Note that products may be nested, in which case they will simply be flattened when reading actual results from a query.

Write Queries

Write queries (e.g. insertions, updates, deletes and table alterations) must be run in a write call.

simplesql's People

Contributors

alwins0n avatar jodersky avatar nivox avatar sunking2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

alwins0n nivox

simplesql's Issues

The column order in the sql queries is significant

As an example, I have the following simple class:

case class Student(firstName: String, lastName: String)derives sq.Reader

This is the function that reads the students:

    def readStudents(cn: Connection, id: Option[Int]): List[Student] = {
        sq.run(cn) {
            var sql = if (id.isEmpty)
                sql"""select last_name, first_name
              from student"""
            else
                sql"select last_name, first_name  from student where student_id =${id.get}"

            sq.read[Student](sql)
        }
    }

Note that in both cases, the last_name field appears on the first position in the select statements. When the data is read, the last_name field populates the firstName member and the first_name populates the firstName member. This makes the code brittle ,imo.

I think it would be better to use a mapping between member names and column names, whether by attributes or convention (case class member names should match exactly the names of the columns, or add a configuration parameter that drives a name transformation).

I really like your library - it is the simplest one I could find among all the scala libraries, the next step would be just to write jdbc code by hand.

Note: the run(jsql.Connection) method doesn't exist in the code, I added it to be able to use the library with the Play framework.

`generating` raises exception with MySQL

Using generating with MysqlDataSource fails with the following exception:

Generated keys not requested. You need to specify Statement.RETURN_GENERATED_KEYS to Statement.executeUpdate(), Statement.executeLargeUpdate() or Connection.prepareStatement().

Even after adding the required flag during the prepared statement creation, the operation still fails with:

java.sql.SQLException: Before start of result set

This is solvable by forcing a res.next() before trying to read the generated key.

MySQL driver version: 8.0.27
Java version: 11.0.9.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.