Improving Wetware

Because technology is never the issue

Elixir Ecto simple SQL Query

Posted by Pete McBreen 21 May 2019 at 06:00

Demo after the previous post, showing just executing SQL

Interactive Elixir (1.8.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> alias Ora.Repo
Ora.Repo
iex(2)> result = Ecto.Adapters.SQL.query!(Repo, "select * from scott.emp where empno = :1 ", [7369])

13:34:54.892 [debug] QUERY OK db=16.0ms
select * from scott.emp where empno = :1  [7369]
%{
  columns: ["EMPNO", "ENAME", "JOB", "MGR", "HIREDATE", "SAL", "COMM", "DEPTNO"],
  num_rows: 1,
  rows: [
    [7369, "SMITH", "CLERK", 7902, ~N[1980-12-17 00:00:00], 800.0, nil, 20]
  ]
}
iex(3)>

Note. Can also use Ecto.Adapters.SQL.query which will then return the usual tuple

iex(3)> result = Ecto.Adapters.SQL.query(Repo, "select * from scott.emp where empno = :1 ", [7369])

13:38:05.739 [debug] QUERY OK db=16.0ms
select * from scott.emp where empno = :1  [7369]
{:ok,
 %{
   columns: ["EMPNO", "ENAME", "JOB", "MGR", "HIREDATE", "SAL", "COMM",
    "DEPTNO"],
   num_rows: 1,
   rows: [
     [7369, "SMITH", "CLERK", 7902, ~N[1980-12-17 00:00:00], 800.0, nil, 20]
   ]
 }}
iex(4)>

Need to set MIX_ENV to dev/test/prod to switch between environments.

Setting up Elixir and Ecto with jamdb_oracle

Posted by Pete McBreen 20 May 2019 at 15:00

Creating a simple Elixir application to test database connectivity to a legacy Oracle database (SCOTT) usign jamdb_oracle. Sorry for the wall of text, but could not find this clearly documented anywhere else, so putting it out here in case I ever need to find it again

C:\Dev\lelixir>mix new ora --sup
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs  
* creating lib
* creating lib/ora.ex
* creating lib/ora/application.ex
* creating test
* creating test/test_helper.exs
* creating test/ora_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd ora
    mix test

Run "mix help" for more commands.

C:\Dev\lelixir>cd ora

C:\Dev\lelixir\ora>

Setup for Oracle, using jamdb_oracle, need to edit ./mix.exs , adding in the extra applications that need to run

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger, :ecto, :jamdb_oracle],
      mod: {Ora.Application, []}

further down add in the dependencies, specifying the versions the application wants from Hex.pm.

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      {:ecto, "~> 3.0"},
      {:jamdb_oracle, "~>0.3.2"}

Then need to run commands to get the dependencies and to compile them. Note that there are extras pulled in when the library you request also has dependencies.

C:\Dev\lelixir\ora>mix deps.get
Resolving Hex dependencies...
Dependency resolution completed:
New:
  base64url 0.0.1
  connection 1.0.4
  db_connection 2.0.6
  decimal 1.7.0
  ecto 3.1.4
  ecto_sql 3.1.3
  jamdb_oracle 0.3.2
  jose 1.9.0
  telemetry 0.4.0
* Getting ecto (Hex package)
* Getting jamdb_oracle (Hex package)
* Getting ecto_sql (Hex package)
* Getting jose (Hex package)
* Getting base64url (Hex package)
* Getting db_connection (Hex package)
* Getting telemetry (Hex package)
* Getting connection (Hex package)
* Getting decimal (Hex package)

Followed by compilation, I got some warnings here, but still worked later on.

C:\Dev\lelixir\ora>mix compile
==> base64url (compile)
Compiled src/base64url.erl
==> connection
Compiling 1 file (.ex)
Generated connection app
==> jose
Compiling 90 files (.erl)
Compiling 8 files (.ex)
warning: function Poison.EncodeError.exception/1 is undefined 
 (module Poison.EncodeError is not available)
  lib/jose/poison/lexical_encoder.ex:8

Generated jose app
===> Compiling telemetry
==> decimal
Compiling 1 file (.ex)
Generated decimal app
==> db_connection
Compiling 16 files (.ex)
Generated db_connection app
==> ecto
Compiling 54 files (.ex)
Generated ecto app
==> ecto_sql
Compiling 25 files (.ex)
Generated ecto_sql app
==> jamdb_oracle
Compiling 5 files (.erl)
Compiling 3 files (.ex)
warning: function table_exists_query/1 required by behaviour Ecto.Adapters.SQL.Connection 
 is not implemented (in module Ecto.Adapters.Jamdb.Oracle.Connection)
  lib/jamdb_oracle_ecto.ex:138

Generated jamdb_oracle app
==> ora
Compiling 2 files (.ex)
Generated ora app

After that had to type mix ecto.gen.repo, Which gave the output

warning: could not find Ecto repos in any of the apps: [:ora].

You can avoid this warning by passing the -r flag or by setting the
repositories managed by those applications in your config/config.exs:

    config :ora, ecto_repos: [...]

** (Mix) ecto.gen.repo expects the repository to be given as -r MyApp.Repo

Which required the following edits to ./config/config.exs

# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config

config :ora, Ora.Repo,
  database: "SCOTT", # original Oracle test database
  username: "user",
  password: "pass",
  hostname: "db.domain.name", 
  port: 1521 # default oracle port

 config :ora, ecto_repos: [Ora.Repo]

rerunning the command was successful, with the message

* creating lib/ora
* creating lib/ora/repo.ex
* updating config/config.exs
Don't forget to add your new repo to your supervision tree
(typically in lib/ora/application.ex):

    # For Elixir v1.5 and later
    {Ora.Repo, []}

    # For Elixir v1.4 and earlier
    supervisor(Ora.Repo, [])

And to add it to the list of ecto repositories in your
configuration files (so Ecto tasks work as expected):

    config :ora,
      ecto_repos: [Ora.Repo]

At this point, ./lib/ora/repo.ex needed a minor edit to use the jamdb adapter

defmodule Ora.Repo do
  use Ecto.Repo,
    otp_app: :ora,
    adapter: Ecto.Adapters.Jamdb.Oracle
end

and ./lib/ora/application.ex needed

  def start(_type, _args) do
    # List all child processes to be supervised
    children = [
      {Ora.Repo, []}
      # Starts a worker by calling: Ora.Worker.start_link(arg)
      # {Ora.Worker, arg}
    ]

At this point, OK to test it out

iex -S mix
Compiling 4 files (.ex)
Generated ora app
Interactive Elixir (1.8.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> alias Ora.Repo
Ora.Repo
iex(2)> import Ecto.Query, only: [from: 2]
Ecto.Query
iex(3)> query = from e in "emp", where: e.ename == "SMITH", select: e.empno
#Ecto.Query
iex(4)> Repo.all(query)

16:10:06.896 [debug] QUERY OK source="emp" db=15.0ms
SELECT n0.empno FROM emp n0 WHERE (n0.ename = 'SMITH') []
[7369]
iex(5)>

Mission accomplished, connected to legacy Oracle database (SCOTT) using Elixir and jamdb_oracle

Thank You for Erlang Joe

Posted by Pete McBreen 19 May 2019 at 04:00

Recently I have been looking at Erlang and Elixir, and in the process was reading Coders at Work and came across this quote from Joe Armstrong (pg 213)

I think the lack of reusability comes in object-oriented languages, not in functional languages. Because the problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

If you have referentially transparent code, if you have pure functions –all the data comes in its input arguments and everything goes out and laves no data behind – it’s incredibly reusable. You can just reuse it here, there and everywhere…

Something to think about.

Blockchain - is it a good idea for some domains?

Posted by Pete McBreen 15 May 2019 at 06:00

Found this set of articles on twitter…

From the history of a bad idea....

When an audience member, tiring of this foggy talk, asked if there was anything concrete that blockchains could offer the NHS, they responded that asking for practical uses of Blockchain was “like trying to predict Facebook in 1993.” The main takeaway for the health care sector people I was with was swearing never to use said accounting firm for anything whatsoever that wasn’t accounting.

Rethinking Driverless Vehicles

Posted by Pete McBreen 10 May 2019 at 13:53

in Nature is suggesting that researchers have made a wrong turn in thinking and writing about Driverless Vehicles

What these academics are not doing is asking the questions that society needs answered to decide what the role of driverless cars will be.

Ashley Nunes suggests

This leads to something many academics overlook: driverless does not mean humanless. My research on the history of technology suggests that such advances might reduce the need for human labour, but it seldom, if ever, eliminates that need entirely. Regulators in the United States and elsewhere have never signed off on the use of algorithms crucial to safety without there being some accompanying human oversight. Rather than rehashing decisions from Philosophy 101, more academics should educate themselves on the history of the technology and the regulatory realities that surround its use.