summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--pom.xml115
-rw-r--r--src/main/scala/org/xapek/influxdb/Influxdb.scala165
-rw-r--r--src/main/scala/org/xapek/influxdb/Main.scala39
-rw-r--r--src/main/scala/org/xapek/influxdb/Sized.scala53
-rw-r--r--src/test/scala/org/xapek/influxdb/AppTest.scala43
-rw-r--r--src/test/scala/org/xapek/influxdb/SizedTest.scala23
7 files changed, 443 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a9a49f0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/target/
+/.cache-*
+/.classpath
+/.project
+/.settings/
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..ba4ce4e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,115 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.xapek</groupId>
+ <artifactId>influxdb-tools</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <inceptionYear>2008</inceptionYear>
+ <properties>
+ <scala.version>2.11.6</scala.version>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>maven-central</id>
+ <name>Maven Central</name>
+ <url>https://repo1.maven.org/maven2</url>
+ </repository>
+ <repository>
+ <id>scala-tools.org</id>
+ <name>Scala-Tools Maven2 Repository</name>
+ <url>http://scala-tools.org/repo-releases</url>
+ </repository>
+ </repositories>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>maven-central</id>
+ <name>Maven Central</name>
+ <url>https://repo1.maven.org/maven2</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>scala-tools.org</id>
+ <name>Scala-Tools Maven2 Repository</name>
+ <url>http://scala-tools.org/repo-releases</url>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.scala-lang</groupId>
+ <artifactId>scala-library</artifactId>
+ <version>${scala.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-actor_2.11</artifactId>
+ <version>2.3.9</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.specs</groupId>
+ <artifactId>specs</artifactId>
+ <version>1.2.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <sourceDirectory>src/main/scala</sourceDirectory>
+ <testSourceDirectory>src/test/scala</testSourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.scala-tools</groupId>
+ <artifactId>maven-scala-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>compile</goal>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <scalaVersion>${scala.version}</scalaVersion>
+ <args>
+ <arg>-target:jvm-1.5</arg>
+ </args>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <configuration>
+ <downloadSources>true</downloadSources>
+ <buildcommands>
+ <buildcommand>ch.epfl.lamp.sdt.core.scalabuilder</buildcommand>
+ </buildcommands>
+ <additionalProjectnatures>
+ <projectnature>ch.epfl.lamp.sdt.core.scalanature</projectnature>
+ </additionalProjectnatures>
+ <classpathContainers>
+ <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
+ <classpathContainer>ch.epfl.lamp.sdt.launching.SCALA_CONTAINER</classpathContainer>
+ </classpathContainers>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.scala-tools</groupId>
+ <artifactId>maven-scala-plugin</artifactId>
+ <configuration>
+ <scalaVersion>${scala.version}</scalaVersion>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+</project>
diff --git a/src/main/scala/org/xapek/influxdb/Influxdb.scala b/src/main/scala/org/xapek/influxdb/Influxdb.scala
new file mode 100644
index 0000000..15e2021
--- /dev/null
+++ b/src/main/scala/org/xapek/influxdb/Influxdb.scala
@@ -0,0 +1,165 @@
+package org.xapek.influxdb
+
+trait InfluxValue {
+ type JavaT
+ def toString(): String
+ def toJava: JavaT
+}
+
+class QueryBuilder1(select: Seq[InfluxColumn]) {
+ def FROM(table: String): QueryBuilder2 = {
+ new QueryBuilder2(select, table)
+ }
+}
+
+class QueryBuilder2(select: Seq[InfluxColumn], from: String) extends QueryBuilder1(select) {
+ def WHERE[E <: Expr](eq: E): QueryBuilder3[E] = {
+ new QueryBuilder3(eq, select, from)
+ }
+
+ override def toString(): String = {
+ "SELECT " + select.mkString(", ") + " FROM " + from
+ }
+}
+
+class QueryBuilder3[WhereT <: Expr](whereExpr: WhereT, select: Seq[InfluxColumn], from: String) extends QueryBuilder2(select, from) {
+ def &&[E2 <: Expr](other: E2): QueryBuilder3[AndExpr[WhereT, E2]] = {
+ new QueryBuilder3(new AndExpr(whereExpr, other), select, from)
+ }
+
+ def ||[E2 <: Expr](other: E2): QueryBuilder3[OrExpr[WhereT, E2]] = {
+ new QueryBuilder3(new OrExpr(whereExpr, other), select, from)
+ }
+
+ def GROUP_BY[ColumnT <% InfluxColumn](column: ColumnT): QueryBuilder4[WhereT] = {
+ new QueryBuilder4(List(column), whereExpr, select, from)
+ }
+
+ override def toString(): String = {
+ super.toString() + " WHERE " + whereExpr.toString()
+ }
+}
+
+class QueryBuilder4[WhereT <: Expr](groupBy: Seq[InfluxColumn], whereExpr: WhereT, select: Seq[InfluxColumn], from: String) extends QueryBuilder3(whereExpr, select, from) {
+ def <<=[ColumnT <% InfluxColumn](column: ColumnT): QueryBuilder4[WhereT] = {
+ val x: InfluxColumn = column
+ new QueryBuilder4(groupBy :+ x, whereExpr, select, from)
+ }
+
+ override def toString(): String = {
+ super.toString() + " GROUP BY " + groupBy.mkString(", ")
+ }
+}
+
+protected trait E {
+ def &&[E2 <: Expr](other: E2): AndExpr[this.type, E2]
+ def ||[E2 <: Expr](other: E2): OrExpr[this.type, E2]
+}
+
+abstract class Expr extends E {
+ def toString(): String
+
+ def &&[E2 <: Expr](other: E2) = {
+ new AndExpr(this, other)
+ }
+
+ def ||[E2 <: Expr](other: E2) = {
+ new OrExpr(this, other)
+ }
+
+ def test(other: Expr): Expr = {
+ return this
+ }
+}
+
+class ValueExpr[ValueT <: InfluxValue](val value: ValueT) extends Expr {
+ override def toString(): String = value.toString
+}
+
+abstract class BinaryOp[E1 <: E, E2 <: E](val op1: E1, val op2: E2) extends Expr {
+ def str: String
+ override def toString(): String = {
+ "(" + op1.toString() + " " + str + " " + op2.toString() + ")"
+ }
+}
+
+class AndExpr[E1 <: E, E2 <: E](op1: E1, op2: E2) extends BinaryOp[E1, E2](op1, op2) {
+ def str = "AND"
+}
+
+class OrExpr[E1 <: E, E2 <: E](op1: E1, op2: E2) extends BinaryOp[E1, E2](op1, op2) {
+ override def str = "OR"
+}
+
+class EqExpr[T <: InfluxValue](column: InfluxColumn, op: ValueExpr[T]) extends BinaryOp[InfluxColumn, ValueExpr[T]](column, op) {
+ def str = "=="
+}
+
+class NeqExpr[T <: InfluxValue](column: InfluxColumn, op: ValueExpr[T]) extends BinaryOp[InfluxColumn, ValueExpr[T]](column, op) {
+ def str = "=="
+}
+
+class InfluxString(val value: String) extends Expr with InfluxValue {
+ type JavaT = String
+ override def toString(): String = {
+ "'" + value.replace("\\", "\\\\").replace("'", "\\'") + "'" // TODO
+ }
+ override def toJava(): String = value
+}
+
+class InfluxNumber(val value: Number) extends Expr with InfluxValue {
+ type JavaT = Number
+
+ override def toString(): String = {
+ value.toString
+ }
+ override def toJava(): Number = value
+}
+
+class InfluxColumn(val name: String) extends Expr {
+ override def toString(): String = {
+ "\"" + name.replace("\\", "\\\\").replace("\"", "\\\"") + "\""
+ }
+
+ def ==[Z <: InfluxValue, ValueT <% Z](value: ValueT): EqExpr[Z] = {
+ new EqExpr(this, new ValueExpr(value))
+ }
+
+ def !=[Z <: InfluxValue, ValueT <% Z](value: ValueT): NeqExpr[Z] = {
+ new NeqExpr(this, new ValueExpr(value))
+ }
+}
+
+object Influxdb {
+ def SELECT(select: Seq[String]): QueryBuilder1 = {
+ new QueryBuilder1(select.map { x: String => influxColumn(x) })
+ }
+
+ def SELECT[ColumnT <% InfluxColumn](select: ColumnT): QueryBuilder1 = {
+ new QueryBuilder1(List(select))
+ }
+
+ def col(col: String): InfluxColumn = {
+ new InfluxColumn(col)
+ }
+
+ implicit def influxString(s: String): InfluxString = {
+ new InfluxString(s)
+ }
+
+ implicit def influxNumber(n: Int): InfluxNumber = {
+ new InfluxNumber(n)
+ }
+
+ implicit def influxNumber(n: Double): InfluxNumber = {
+ new InfluxNumber(n)
+ }
+
+ implicit def influxColumn(s: String): InfluxColumn = {
+ new InfluxColumn(s)
+ }
+
+ implicit def queryToString(q: QueryBuilder2): String = q.toString
+ implicit def queryToString[T <: Expr](q: QueryBuilder3[T]): String = q.toString
+ implicit def queryToString[T <: Expr](q: QueryBuilder4[T]): String = q.toString
+}
diff --git a/src/main/scala/org/xapek/influxdb/Main.scala b/src/main/scala/org/xapek/influxdb/Main.scala
new file mode 100644
index 0000000..c56d3bb
--- /dev/null
+++ b/src/main/scala/org/xapek/influxdb/Main.scala
@@ -0,0 +1,39 @@
+package org.xapek.influxdb
+
+import akka.actor.Actor
+import akka.actor.Props
+import akka.event.Logging
+import akka.actor.ActorDSL
+import akka.actor.ActorSystem
+import akka.actor.ActorLogging
+import org.xapek.influxdb.Influxdb._
+
+case class Row(columns: Seq[String])
+
+case class Write(measurement: String, columns: Seq[String])
+class GenericReader(query: String) extends Actor with ActorLogging {
+ def receive = {
+ case row: Row => log.info("Thanks for the pint: " + row.columns.toString())
+ }
+}
+
+object MyReader extends GenericReader(Influxdb SELECT "value" FROM "test" WHERE col("time") == 30)
+
+
+
+
+object Main {
+
+ def main(args: Array[String]): Unit = {
+ // val system = ActorSystem("test")
+ // val alice = system.actorOf(Props(MyReader), "alice")
+ //
+ // alice ! new Row(List("a"))
+ //
+ // system.shutdown()
+ //
+ // val x : Tuple2[Int,Int] = (1,2)
+
+ }
+}
+
diff --git a/src/main/scala/org/xapek/influxdb/Sized.scala b/src/main/scala/org/xapek/influxdb/Sized.scala
new file mode 100644
index 0000000..fc402cd
--- /dev/null
+++ b/src/main/scala/org/xapek/influxdb/Sized.scala
@@ -0,0 +1,53 @@
+package org.xapek.influxdb
+
+/**
+ * Partial re-implementation of Sized and Nat type from https://github.com/milessabin/shapeless
+ */
+
+/** Natural Number Type */
+trait Nat {
+ type N <: Nat
+}
+
+/** Successor */
+case class Succ[P <: Nat]() extends Nat {
+ type N = Succ[P]
+}
+
+/** Zero */
+class _0 extends Nat with Serializable {
+ type N = _0
+}
+
+/** Nat type to Int value conversion */
+trait ToInt[N <: Nat] extends Serializable {
+ def apply(): Int
+}
+
+object ToInt {
+ def apply[N <: Nat](implicit toInt: ToInt[N]): ToInt[N] = toInt
+
+ implicit val toInt0 = new ToInt[_0] {
+ def apply() = 1
+ }
+ implicit def toIntSucc[N <: Nat](implicit toIntN: ToInt[N]) = new ToInt[Succ[N]] {
+ def apply() = toIntN() + 1
+ }
+}
+
+/** Seq with size coded in type */
+class Sized[Repr, L <: Nat](val unsized: Seq[Repr]) extends AnyVal {
+ override def toString = unsized.toString
+}
+
+object SizedOp {
+ def wrap[Repr, L <: Nat](r: Repr) = new Sized[Repr, _0](List(r))
+
+ def add[Repr, L <: Nat](s: Sized[Repr, L], r: Repr) = new Sized[Repr, Succ[L]](s.unsized ++ List(r))
+
+ def toInt[N <: Nat](implicit toIntN: ToInt[N]) = toIntN()
+
+ def toInt(n: Nat)(implicit toIntN: ToInt[n.N]) = toIntN()
+
+ def count[Repr, M <: Nat](s: Sized[Repr, M])(implicit ev: ToInt[M]) = toInt[M]
+} \ No newline at end of file
diff --git a/src/test/scala/org/xapek/influxdb/AppTest.scala b/src/test/scala/org/xapek/influxdb/AppTest.scala
new file mode 100644
index 0000000..26ed08f
--- /dev/null
+++ b/src/test/scala/org/xapek/influxdb/AppTest.scala
@@ -0,0 +1,43 @@
+package org.xapek.influxdb
+
+import org.junit._
+import Assert._
+import org.xapek.influxdb.Influxdb._
+
+@Test
+class AppTest {
+
+ @Test
+ def testStatements() = {
+ assertTrue((Influxdb SELECT "foo" FROM "bla" WHERE col("a") == "asd")
+ .toString().contains("as"))
+
+ assertTrue((Influxdb SELECT List("foo", "bla") FROM "bla" WHERE col("a") == "asd")
+ .toString().contains("foo"))
+
+ assertTrue((Influxdb SELECT List("foo", "bla") FROM "bla" WHERE col("a") == 1)
+ .toString().contains("== 1"))
+
+ assertTrue((Influxdb
+ SELECT col("foo")
+ FROM "bla"
+ WHERE col("a") == "asd" || col("b") == "C" && col("c") == "d").toString().contains("bla"))
+
+ assertTrue((Influxdb
+ SELECT "foo"
+ FROM "bla"
+ WHERE (col("a") == "asd" || col("b") == "C") && col("c") == "d").toString().contains("foo"))
+
+ assertTrue((Influxdb
+ SELECT "foo"
+ FROM "bla"
+ WHERE (col("a") == "asd" || col("b") == "C") && col("c") == "d"
+ GROUP_BY "asd").toString().contains("GROUP BY"))
+
+ assertTrue((Influxdb
+ SELECT col("foo")
+ FROM "bla"
+ WHERE (col("a") == "asd" || col("b") == "C") && col("c") == "d"
+ GROUP_BY "asd" <<= "asd2").toString().contains("asd2"))
+ }
+}
diff --git a/src/test/scala/org/xapek/influxdb/SizedTest.scala b/src/test/scala/org/xapek/influxdb/SizedTest.scala
new file mode 100644
index 0000000..5f51e91
--- /dev/null
+++ b/src/test/scala/org/xapek/influxdb/SizedTest.scala
@@ -0,0 +1,23 @@
+package org.xapek.influxdb
+
+import org.junit._
+import org.junit.Assert._
+import org.xapek.influxdb.Influxdb._
+
+@Test
+class SizedTest {
+ @Test
+ def testStatements() = {
+ val s1 = SizedOp.wrap("abc")
+ assertEquals(1, SizedOp.count(s1))
+ assertEquals(List("abc"), s1.unsized)
+
+ val s2 = SizedOp.add(s1, "cde")
+ assertEquals(2, SizedOp.count(s2))
+ assertEquals(List("abc", "cde"), s2.unsized)
+
+ val s3 = SizedOp.add(s2, "fgh")
+ assertEquals(SizedOp.count(s3), 3)
+ assertEquals(List("abc", "cde", "fgh"), s3.unsized)
+ }
+}