<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexander Radzin</title>
    <description>The latest articles on DEV Community by Alexander Radzin (@alexradzin).</description>
    <link>https://dev.to/alexradzin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F391234%2Faf7715e0-bc1d-4225-908e-2ff1e693d2b0.jpeg</url>
      <title>DEV Community: Alexander Radzin</title>
      <link>https://dev.to/alexradzin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexradzin"/>
    <language>en</language>
    <item>
      <title>Extending the Aerospike JDBC driver with UDFs</title>
      <dc:creator>Alexander Radzin</dc:creator>
      <pubDate>Tue, 02 Jun 2020 19:25:59 +0000</pubDate>
      <link>https://dev.to/alexradzin/extending-the-aerospike-jdbc-driver-with-udfs-5gei</link>
      <guid>https://dev.to/alexradzin/extending-the-aerospike-jdbc-driver-with-udfs-5gei</guid>
      <description>&lt;h1&gt;
  
  
  Preface
&lt;/h1&gt;

&lt;p&gt;This post continues series of articles that present the &lt;a href="https://dev.to/alexradzin/introduction-to-the-aerospike-jdbc-driver-51m4"&gt;Aerosplike SQL driver&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Previous &lt;a href="https://dev.to/alexradzin/functions-supported-by-the-aerospike-sql-driver-2l0p"&gt;post&lt;/a&gt; explained the built-in functions provided by the Aerospike JDBC Driver. Here I am going to explain how to extend the functionality of the driver by implementing User Defined Functions (UDF).&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementation of UDF
&lt;/h1&gt;

&lt;p&gt;Right now aggregate functions cannot be customized, however you can implement scalar and collection functions using Java programming language. &lt;/p&gt;

&lt;p&gt;Function is a named block of reusable code that used to perform single action. Typically functions return result. Functions may accept arguments. &lt;/p&gt;

&lt;p&gt;Java 8 and higher provides interfaces &lt;code&gt;Supplier&lt;/code&gt;, &lt;code&gt;Function&lt;/code&gt;, &lt;code&gt;BiFunction&lt;/code&gt;. Implementations of these interfaces can be defined as UDF for the Aerospike JDBC driver. For example here is definition of function &lt;code&gt;now()&lt;/code&gt; that returns epoch in milliseconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Now&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Supplier&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is example of function that receives one argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Lower&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Implementation of function that accepts 2 arguments is similar. Create class that implements &lt;code&gt;BiFunction&lt;/code&gt;. Unfortunately JDK does not define interface for function that accepts 3, 4 or more arguments as well as function that accepts any number of arguments. Such interface is defined by the driver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.nosqldriver.util&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;@FunctionalInterface&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;VarargsFunction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;R&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you want to implement UDF that accepts more than 2 arguments you have to implement this interface. In this case you have to add the driver to the compilation class path. Implementation of other types of functions does not require this dependency. Implementation of &lt;code&gt;VarargsFunction&lt;/code&gt; has yet another complexity: the programmer is responsible on casting and verification of accepted arguments. &lt;/p&gt;

&lt;h1&gt;
  
  
  Deploying of UDF
&lt;/h1&gt;

&lt;p&gt;Once UDF is implemented and verified it should be packed into jar file that should be added to the classpath of the driver. Various tools allow this. For example &lt;a href="https://dbeaver.io/"&gt;Dbeaver&lt;/a&gt; and &lt;a href="http://squirrel-sql.sourceforge.net/"&gt;SquirreL&lt;/a&gt; allow defining driver packaged in several jar files. Once this is done the the function should be registered using connection parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;custom.function.NAME=FULLY_QUALIFIED_CLASS_NAME
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;custom.function.now=com.mycompany.Now
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The connection parameter can be supplied as a parameter of JDBC URL or as a connection property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jdbc:aeropspike:myhost?custom.function.now=com.mycompany.Now
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once function is registered it can be used in SQL query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver"&gt;Aerospike JDBC Driver&lt;/a&gt; provides a comprehensive set of built-in functions. Moreover it is extendable using User-Defined Functions that can be easily implemented using Java programming language. &lt;/p&gt;

&lt;h1&gt;
  
  
  Project home
&lt;/h1&gt;

&lt;p&gt;The project is available in &lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's next
&lt;/h1&gt;

&lt;p&gt;Next article of this series will explain how to work with complex types.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>java</category>
      <category>sql</category>
      <category>driver</category>
    </item>
    <item>
      <title>Functions supported by the Aerospike SQL driver</title>
      <dc:creator>Alexander Radzin</dc:creator>
      <pubDate>Fri, 29 May 2020 05:29:31 +0000</pubDate>
      <link>https://dev.to/alexradzin/functions-supported-by-the-aerospike-sql-driver-2l0p</link>
      <guid>https://dev.to/alexradzin/functions-supported-by-the-aerospike-sql-driver-2l0p</guid>
      <description>&lt;h1&gt;
  
  
  Preface
&lt;/h1&gt;

&lt;p&gt;This post continues &lt;a href="https://dev.to/alexradzin/introduction-to-the-aerospike-jdbc-driver-51m4"&gt;series of articles&lt;/a&gt; that present the &lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver"&gt;Aerosplike SQL driver&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;There are two types of SQL functions, aggregate functions, and scalar(non-aggregate) functions. Aggregate functions operate on many records and produce a summary, works with GROUP BY whereas non-aggregate functions operate on each record independently.&lt;a href="https://www.w3resource.com/sql/sql-functions.php"&gt;[1]&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This statement is correct for the most of relational databases that can store only simple type in one cell. Aerospike supports built-in lists and maps. &lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver"&gt;Aerospike JDBC driver&lt;/a&gt; provides several functions that operate these types. Since lists and maps are not scalars we can define 3 types of functions provided by the Aerospike JDBC driver:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scalar functions (that operate scalar types into one record)&lt;/li&gt;
&lt;li&gt;collection functions (that operate lists and maps into one record)&lt;/li&gt;
&lt;li&gt;aggregate functions that operate many records&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Built-in scalar and collection functions
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;len(x)&lt;/code&gt;, &lt;code&gt;length(x)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;returns length of given string, list, map&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ascii(c)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns ASCII code of given character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;char(c)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns char corresponding to the given ASCII code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;locate(subStr, str, [offset=1])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns position of &lt;code&gt;subStr&lt;/code&gt; into &lt;code&gt;str&lt;/code&gt; starting from &lt;code&gt;offset&lt;/code&gt; (that is 1 if omitted)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;instr(subStr, str)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns position of &lt;code&gt;subStr&lt;/code&gt; into &lt;code&gt;str&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;trim(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;trims string (removes spaces from both sides)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ltrim(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;removes leading spaces from the string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rtrim(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;removes trailing spaces from the string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strcmp(s1, s2)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;compares given strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;left(s, n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns substring of length &lt;code&gt;n&lt;/code&gt; starting from the beginning of the given string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lower(s)&lt;/code&gt;, &lt;code&gt;lcase(s)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;converts a string to lower-case&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;upper(s)&lt;/code&gt;, &lt;code&gt;ucase(s)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;converts a string to upper-case&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;str(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns string representation of given value (like &lt;code&gt;toString()&lt;/code&gt; in java)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;space(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns string that contains &lt;code&gt;n&lt;/code&gt; spcaces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reverse(s)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;reverses given string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;to_base64(bytes)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;generates Base64 representation of given byte array&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;from_base64(str)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns byte array from given Base64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;substr(str, from, to)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns substring of given string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;concat(str1, str2, ...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;concatenates given strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;concat_ws(separator, str1, str2, ...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;concatenates given strings using separator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;date([x])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;creates &lt;code&gt;java.util.Date&lt;/code&gt; from either string or epoch. If argument is not provided this function returns date that represents current time.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;calendar([x])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;similar to &lt;code&gt;date([x]) but returns&lt;/code&gt;java.util.Calendar`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;now()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns epoch (ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;year([x])&lt;/code&gt;, &lt;code&gt;month([x])&lt;/code&gt;, &lt;code&gt;dayofmonth([x])&lt;/code&gt;, &lt;code&gt;hour([x])&lt;/code&gt;, &lt;code&gt;minute([x])&lt;/code&gt; ,&lt;code&gt;second([x])&lt;/code&gt;, &lt;code&gt;millisecond([x])&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;return year, month, etc respectively. Optional argument may be either formatted date or epoch in milliseconds. If it is not provided current time is used.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;map(s)&lt;/code&gt;, &lt;code&gt;list(s)&lt;/code&gt;, &lt;code&gt;array(s)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;create map, list and array respectively from their string representation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Built-in aggregate functions
&lt;/h1&gt;

&lt;p&gt;The aggregate functions allow you to perform a calculation on a set of values to return a single scalar value. The following functions are supported:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;count()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sum()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;min()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;avg()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sumsqs()&lt;/code&gt; - sum of squares of values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Distinct is considered a modifier but syntactically looks like are  function and is supported as well. &lt;/p&gt;

&lt;p&gt;For performance and better memory consumption reasons aggregate functions are implemented in Lua and run on server side (into Aerospike DB).&lt;/p&gt;

&lt;h1&gt;
  
  
  Project home
&lt;/h1&gt;

&lt;p&gt;The project is available in &lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's next
&lt;/h1&gt;

&lt;p&gt;Next article of this series will explain how to add custom function to the driver.&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>java</category>
      <category>sql</category>
      <category>driver</category>
    </item>
    <item>
      <title>Aerospike JDBC driver: SQL DML compliance</title>
      <dc:creator>Alexander Radzin</dc:creator>
      <pubDate>Wed, 27 May 2020 16:35:03 +0000</pubDate>
      <link>https://dev.to/alexradzin/aerospike-jdbc-driver-sql-dml-compliance-58ba</link>
      <guid>https://dev.to/alexradzin/aerospike-jdbc-driver-sql-dml-compliance-58ba</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;My previous post explained &lt;a href="https://dev.to/alexradzin/aerospike-jdbc-driver-sql-ddl-compliance-23bc"&gt;SQL DDL commands&lt;/a&gt; supported by the Aerospike JDBC driver. This post will discuss the DML commands.&lt;/p&gt;

&lt;h1&gt;
  
  
  DML - data manipulation language
&lt;/h1&gt;

&lt;p&gt;Data manipulation language consists of the following commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;INSERT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SELECT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UPDATE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aerospike JDBC driver treats Aerospoike sets as tables, and bins as columns. However Aerospike is not relational database. It treats key and value differently. Key is not a regular column. Aerospike JDBC driver uses special identifier &lt;code&gt;PK&lt;/code&gt; to refer the primary key. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;INSERT&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Insert for Aerospike is more than insert. Since Aerospike is schemaless, schema is actually defined by the data. Table (set) is created when data is written there. The actual data "defines" the table schema, i.e. types and name of table columns (or set bins using  Aerospike terms.)&lt;/p&gt;

&lt;p&gt;Insert syntax is not differ from syntax of regular SQL. You can either insert one row:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'John'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Lennon'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1940&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;or several rows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="k"&gt;values&lt;/span&gt; 
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'John'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Lennon'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1940&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Paul'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'McCartney'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1942&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Important&lt;/em&gt;: primary key (PK) is required in &lt;code&gt;INSERT&lt;/code&gt; statement. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;SELECT&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Select statement is used in order to retrieve data from the table. Either explicit definition of columns to be retrieved or * are supported:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Data can be filtered using &lt;code&gt;WHERE&lt;/code&gt; statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'John'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Unlike &lt;a href="https://www.aerospike.com/docs/tools/aql/"&gt;AQL&lt;/a&gt; where clause here can use expressions, calculations, functions, parentheses and refer &lt;code&gt;PK&lt;/code&gt; or any bin name (column) either indexed or not. Logical operations &amp;lt;, &amp;lt;. &amp;gt;=, &amp;lt;=, =, !=, IN operator and LIKE statement for textual fields are supported as well.  &lt;code&gt;BETWEEN&lt;/code&gt; statement is supported for numeric values only.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Bill'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;PK&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;PK&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Rows returned by &lt;code&gt;select&lt;/code&gt; can be sorted using &lt;code&gt;ORDER BY&lt;/code&gt; and sliced using &lt;code&gt;LIMIT&lt;/code&gt; and &lt;code&gt;OFFSET&lt;/code&gt;. Inner &lt;code&gt;SELECT&lt;/code&gt; statements are supported. &lt;/p&gt;

&lt;h2&gt;
  
  
  JOIN
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Select&lt;/code&gt; can be used with &lt;code&gt;join&lt;/code&gt;. Inner and left joins are supported. The join expression can use equality expression on any column. &lt;code&gt;PK&lt;/code&gt; can be used for the right table. Using &lt;code&gt;PK&lt;/code&gt; on the left table is possible if &lt;code&gt;PK&lt;/code&gt; is stored in the DB (that does not happen by default). One of the next posts will be dedicated to details of using &lt;code&gt;PK&lt;/code&gt; in queries. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;UPDATE&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Update&lt;/code&gt; and &lt;code&gt;insert&lt;/code&gt; in AQL are similar. Both commands add new record if specified &lt;code&gt;PK&lt;/code&gt; does not exist and update record if &lt;code&gt;PK&lt;/code&gt; exists. &lt;code&gt;Update&lt;/code&gt; implemented by Aersoplike SQL driver behave like the standard SQL update. It updates records found by criteria specified in &lt;code&gt;WHERE&lt;/code&gt; clause. &lt;code&gt;WHERE&lt;/code&gt; expression can be complex (see &lt;code&gt;SELECT&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;DELETE&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Unlike &lt;code&gt;DELETE&lt;/code&gt; implemented by AQL that can delete entries only identified by &lt;code&gt;PK&lt;/code&gt; this &lt;code&gt;delete&lt;/code&gt; works with regular &lt;code&gt;where&lt;/code&gt; clause (see &lt;code&gt;update&lt;/code&gt;).&lt;/p&gt;

&lt;h1&gt;
  
  
  Project home
&lt;/h1&gt;

&lt;p&gt;The project is available in &lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver/"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's next
&lt;/h1&gt;

&lt;p&gt;Next article of this series will explain how to use built-in functions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Previous
&lt;/h1&gt;

&lt;p&gt;Aerospike JDBC driver: &lt;a href="https://dev.to/alexradzin/aerospike-jdbc-driver-sql-ddl-compliance-23bc"&gt;SQL DDL compliance&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>java</category>
      <category>sql</category>
      <category>jdbc</category>
    </item>
    <item>
      <title>Aerospike JDBC driver: SQL DDL compliance</title>
      <dc:creator>Alexander Radzin</dc:creator>
      <pubDate>Tue, 26 May 2020 18:37:09 +0000</pubDate>
      <link>https://dev.to/alexradzin/aerospike-jdbc-driver-sql-ddl-compliance-23bc</link>
      <guid>https://dev.to/alexradzin/aerospike-jdbc-driver-sql-ddl-compliance-23bc</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;My previous &lt;a href="https://dev.to/alexradzin/introduction-to-the-aerospike-jdbc-driver-51m4"&gt;post&lt;/a&gt; has introduced to reader the Aerospike JDBC driver. This post explains one of its feature - DDL.&lt;/p&gt;

&lt;h1&gt;
  
  
  DDL - data definition language
&lt;/h1&gt;

&lt;p&gt;Typical relational database requires schema definition. DDL commands can create schemas, tables, indexes etc. Aerospike is a schemaless database. Namespace cannot be created dynamically: it must be configured using configuration file. Aerospike set (similar to table in a relational database) should not be created explicitly: it is created automatically when data is being written.&lt;/p&gt;

&lt;p&gt;Secondary indices exist in Aerospike as well as relational databases and can be created and dropped dynamically. Aerospike JDBC driver supports commands CREATE INDEX and DROP INDEX. &lt;/p&gt;

&lt;p&gt;Relational database "knows" type of indexed field, so it should not be mentioned in "CREATE INDEX" statement. Aerospike is schemaless DB, so the index type is defined when index is being created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;STRING&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;INDEX1&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;MYTABLE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SOME_FIELD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Generally syntax of create index statement looks like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;index_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;set_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;bin_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The following index types are supported: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;STRING&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NUMERIC&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GEO2DSPHERE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STRING MAPKEYS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STRING MAPVALUES&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NUMERIC LIST&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dropping index is simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;set_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;bin_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;MYTABLE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INDEX1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Project home
&lt;/h1&gt;

&lt;p&gt;The project is available in &lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver/"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's next
&lt;/h1&gt;

&lt;p&gt;Next article of this series will explain the SQL DML compliance.&lt;/p&gt;

&lt;h1&gt;
  
  
  Previous
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://dev.to/alexradzin/introduction-to-the-aerospike-jdbc-driver-51m4"&gt;Introduction to the Aerospike JDBC driver&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aerospike</category>
      <category>java</category>
      <category>sql</category>
      <category>jdbc</category>
    </item>
    <item>
      <title>Introduction to the Aerospike JDBC driver</title>
      <dc:creator>Alexander Radzin</dc:creator>
      <pubDate>Mon, 25 May 2020 15:36:23 +0000</pubDate>
      <link>https://dev.to/alexradzin/introduction-to-the-aerospike-jdbc-driver-51m4</link>
      <guid>https://dev.to/alexradzin/introduction-to-the-aerospike-jdbc-driver-51m4</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Once upon a time when all databases were relational and supported SQL, Java programmers (almost) did not care about the database type they were going to use. This was achieved by using JDBC drivers - software that talks to the specific database exposing standard API to the application layer.&lt;/p&gt;

&lt;p&gt;The world has changed after the invention of NoSQL databases. These databases have some advantages comparing to the traditional relational databases but they do not have common interface. Therefore, using them requires writing specific application code for each database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.aerospike.com/"&gt;Aerospike&lt;/a&gt; is a popular, fast, mature NoSQL database. It provides client libraries for different systems and languages including Java. These libraries help to implement applications that use Aerospike DB. However, application code which uses this library has to be specific for Aerospike. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver/"&gt;Aerospike JDBC Driver&lt;/a&gt; enables users to connect with Aerospike DB directly from any application that supports standard JDBC connectivity. &lt;/p&gt;

&lt;h1&gt;
  
  
  Key features
&lt;/h1&gt;

&lt;p&gt;This is a JDBC driver. It can be used by any JDBC complaint application, e.g. UI, monitoring, querying and other general purpose tools. It supports standard SQL statements and functions and can be used by developers, QA, data analysts and DevOps engineers. It can help if somebody wants to migrate his application from relational DB to Aerospike.&lt;/p&gt;

&lt;p&gt;This article will briefly enumerate the key features of the driver. The next articles of this series will explain particular features in depth.&lt;/p&gt;

&lt;h1&gt;
  
  
  SQL compliance
&lt;/h1&gt;

&lt;h2&gt;
  
  
  DDL
&lt;/h2&gt;

&lt;p&gt;CREATE INDEX&lt;br&gt;
DROP INDEX&lt;/p&gt;

&lt;h2&gt;
  
  
  DML
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;INSERT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SELECT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UPDATE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt; - using PK or any other column and the combination of them including calculations, parentheses etc.&lt;br&gt;
&lt;code&gt;JOIN&lt;/code&gt;,  LEFT JOIN&lt;code&gt;&lt;br&gt;
&lt;/code&gt;GROUP BY`&lt;/p&gt;

&lt;h1&gt;
  
  
  Data types
&lt;/h1&gt;

&lt;p&gt;The driver supports all basic Aerospike types (integer, string, bytes, &lt;br&gt;
double) mapping them to JDBC types (&lt;code&gt;INTEGER&lt;/code&gt;, &lt;code&gt;VARCHAR&lt;/code&gt;, &lt;code&gt;BLOB&lt;/code&gt;, &lt;code&gt;DOUBLE&lt;/code&gt;) respectively and corresponding java types (&lt;code&gt;int&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;byte[]&lt;/code&gt;, &lt;code&gt;double&lt;/code&gt;). Aerospike lists and maps are supported as well. They are mapped to the JDBC &lt;code&gt;java.sql.Array&lt;/code&gt; and java.util.Map respectively. &lt;/p&gt;

&lt;p&gt;Additionally driver can store and retrieve java objects using either standard java serialization mechanism (for &lt;code&gt;Serializable&lt;/code&gt; or &lt;code&gt;Externalizable&lt;/code&gt; classes) or using custom serialization/deserialization) enabled by user defined functions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Expressions and functions
&lt;/h1&gt;

&lt;p&gt;Mathematical expressions can be used in the queries:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
select first_name, last_name, year()-year_of_birth as age from people&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in Functions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;aggregation functions: &lt;code&gt;count()&lt;/code&gt;, &lt;code&gt;max()&lt;/code&gt;, &lt;code&gt;min()&lt;/code&gt;, &lt;code&gt;sum()&lt;/code&gt;, &lt;code&gt;avg()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;string functions: &lt;code&gt;str()&lt;/code&gt;, &lt;code&gt;concat()&lt;/code&gt;, &lt;code&gt;ucase()&lt;/code&gt;, &lt;code&gt;lcase()&lt;/code&gt;, &lt;code&gt;len()&lt;/code&gt;, reverse() etc.&lt;/li&gt;
&lt;li&gt;date/time functions: &lt;code&gt;now()&lt;/code&gt;, &lt;code&gt;year()&lt;/code&gt;, &lt;code&gt;month()&lt;/code&gt;, &lt;code&gt;day()&lt;/code&gt; etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  User-defined functions
&lt;/h2&gt;

&lt;p&gt;The driver provides a lot of built-in functions. Moreover, it can be easily extended. User can implement his own functions in Java and register them via JDBC connection parameters.&lt;/p&gt;

&lt;h1&gt;
  
  
  Project home
&lt;/h1&gt;

&lt;p&gt;The project is available in &lt;a href="https://github.com/alexradzin/aerospike-jdbc-driver/"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's next
&lt;/h1&gt;

&lt;p&gt;Next &lt;a href="https://dev.to/alexradzin/aerospike-jdbc-driver-sql-ddl-compliance-23bc"&gt;article&lt;/a&gt; of this series will explain the SQL compliance of the driver.&lt;/p&gt;

</description>
      <category>aeropsike</category>
      <category>java</category>
      <category>sql</category>
      <category>jdbc</category>
    </item>
  </channel>
</rss>
