Skip to content

Commit

Permalink
add basic ability to create hsqldb TEXT tables using @Csv annotatio…
Browse files Browse the repository at this point in the history
…n and then adding the file source for the class. bump groovy version. Coincidentally both groovy and hsqldb are 2.3.2 :)
  • Loading branch information
kdabir committed May 28, 2014
1 parent f2c2537 commit 641ed69
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ feature complete. The project is under active development and is not yet suitabl

### v0.7
- support `@WithoutId` annotation to map to tables that do not have any id field and hence classes will not have id specific methods
- first cut of support for `@Csv` annotation to open CSV files as table. File can be set using `setCsvFile()` method of Gstorm.
- capability to provide custom type mappings as well changing the default type mapping if no type mapping is found
- ability to chain `stormify` and return the `Gstorm` instance

Expand Down
9 changes: 5 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apply plugin: 'groovy'

group = 'io.github.kdabir.gstorm'
version = '0.7-SNAPSHOT'
version = '0.7'
description = "Groovy Single Table ORM"

sourceSets {
Expand All @@ -14,9 +14,10 @@ repositories {
}

dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.1',
compile 'org.codehaus.groovy:groovy-all:2.3.2',
'org.hsqldb:hsqldb:2.3.2'
testCompile 'junit:junit:4.10'
testCompile 'junit:junit:4.10',
'io.github.kdabir.directree:directree:0.2'
}

task wrapper(type: Wrapper) {
Expand Down Expand Up @@ -59,7 +60,7 @@ bintray {
desc = projectDescription
licenses = ['MIT']
}
dryRun = true // whether to run this as dry-run, without deploying
// dryRun = true // whether to run this as dry-run, without deploying
}

String getPropertyOrUseDefault(String propertyName, String defaultValue) {
Expand Down
9 changes: 9 additions & 0 deletions src/gstorm/Csv.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package gstorm

import java.lang.annotation.Retention

import static java.lang.annotation.RetentionPolicy.RUNTIME

@Retention(RUNTIME)
@interface Csv {
}
4 changes: 4 additions & 0 deletions src/gstorm/Gstorm.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class Gstorm {
sql.execute(new CreateTableQueryBuilder(metaData).build())
}

def setCsvFile(Class modelClass, String filePath, boolean readOnly=false) {
def tableName = new ClassMetaData(modelClass).tableName
sql.execute(""" SET TABLE $tableName SOURCE "$filePath" ${(readOnly)?"DESC":""}""".toString())
}

def enableQueryLogging(level = Level.FINE) {
def sqlMetaClass = Sql.class.metaClass
Expand Down
2 changes: 1 addition & 1 deletion src/gstorm/ModelClassEnhancer.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ModelClassEnhancer {
ModelClassEnhancer(ClassMetaData classMetaData, Sql sql) {
this.metaData = classMetaData
this.sql = sql
this.canAddIdBasedMethods = !metaData.withoutId()
this.canAddIdBasedMethods = !metaData.isWithoutId()
}

public void enhance() {
Expand Down
12 changes: 9 additions & 3 deletions src/gstorm/builders/CreateTableQueryBuilder.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ class CreateTableQueryBuilder extends AbstractQueryBuilder {
def tableName = classMetaData.tableName
def columnDefs = classMetaData.fields.collect { field -> "${field.name} ${field.columnType}" }

if (!classMetaData.withoutId()) {
columnDefs.add(0,"${classMetaData.idFieldName ?: 'ID'} NUMERIC GENERATED ALWAYS AS IDENTITY PRIMARY KEY")
if (!classMetaData.isWithoutId()) {
columnDefs.add(0, "${classMetaData.idFieldName ?: 'ID'} NUMERIC GENERATED ALWAYS AS IDENTITY PRIMARY KEY")
}
"CREATE TABLE IF NOT EXISTS $tableName (${columnDefs.join(', ')})".toString()

new StringBuilder("CREATE").append(SPACE)
.append(classMetaData.isCsv() ? 'TEXT TABLE' : 'TABLE').append(SPACE)
.append("IF NOT EXISTS").append(SPACE)
.append(tableName).append(SPACE)
.append("(${ columnDefs.join(', ') })")
.toString()
}
}
7 changes: 6 additions & 1 deletion src/gstorm/metadata/ClassMetaData.groovy
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package gstorm.metadata

import gstorm.Csv
import gstorm.Id
import gstorm.Table
import gstorm.WithoutId
Expand Down Expand Up @@ -41,10 +42,14 @@ class ClassMetaData {
modelClass.getAnnotation(Table)?.value()?.trim() ?: modelClass.simpleName
}

boolean withoutId() {
boolean isWithoutId() {
modelClass.isAnnotationPresent(WithoutId)
}

boolean isCsv(){
modelClass.isAnnotationPresent(Csv)
}

private List<FieldMetaData> getOtherFieldsOfClass(Class modelClass) {
fieldsDeclaredIn(modelClass)
.findAll { !it.isAnnotationPresent(Id) }
Expand Down
58 changes: 58 additions & 0 deletions test/gstorm/GstormCsvIntgTest.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package gstorm

import directree.DirTree
import groovy.sql.Sql
import models.ClassWithCsvAnnotation
import org.junit.After
import org.junit.Before
import org.junit.Test

class GstormCsvIntgTest {

Gstorm gstorm
Sql sql

@Before
void setUp() {
DirTree.create("tmp") {
dir("csvtest") {
file("test1.csv") {
"""|id,name
|1,test
""".stripMargin("|")
}
}
}
sql = Sql.newInstance("jdbc:hsqldb:file:tmp/csvtest/db", "sa", "", "org.hsqldb.jdbc.JDBCDriver")
gstorm = new Gstorm(sql)
gstorm.stormify(ClassWithCsvAnnotation)
}

@After
void tearDown() {
sql.execute("drop table ClassWithCsvAnnotation if exists")
sql.close()
}

@Test
void "should load the data from CSV"() {
gstorm.setCsvFile(ClassWithCsvAnnotation, 'test1.csv;ignore_first=true')

assert ClassWithCsvAnnotation.all.size() == 1
}

@Test
void "should write the data to CSV"() {
gstorm.setCsvFile(ClassWithCsvAnnotation, 'test1.csv;ignore_first=true')
new ClassWithCsvAnnotation(name: "another_text_123").save()

assert ClassWithCsvAnnotation.all.size() == 2
assert new File("tmp/csvtest/test1.csv").text.contains("another_text_123")
}

@Test(expected = java.sql.SQLException)
void "should be able to open csv as read only"() {
gstorm.setCsvFile(ClassWithCsvAnnotation, 'test1.csv;ignore_first=true', true)
new ClassWithCsvAnnotation(name: "another_text_123").save()
}
}
18 changes: 18 additions & 0 deletions test/gstorm/builders/CreateTableQueryBuilderTest.groovy
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package gstorm.builders

import gstorm.metadata.ClassMetaData
import models.ClassWithCsvAnnotation
import models.ClassWithIdAnnotation
import models.ClassWithoutId
import models.Person

class CreateTableQueryBuilderTest extends GroovyTestCase {
Expand All @@ -27,5 +29,21 @@ class CreateTableQueryBuilderTest extends GroovyTestCase {
"uid NUMERIC GENERATED ALWAYS AS IDENTITY PRIMARY KEY, " +
"name VARCHAR(255))"
}

void "test builds query without id"() {
CreateTableQueryBuilder builder = new CreateTableQueryBuilder(new ClassMetaData(ClassWithoutId.class))

assert builder.build() == "CREATE TABLE IF NOT EXISTS ClassWithoutId (" +
"name VARCHAR(255), " +
"description VARCHAR(255))"
}

void "test builds query for text tables for CSV annotated classes"() {
CreateTableQueryBuilder builder = new CreateTableQueryBuilder(new ClassMetaData(ClassWithCsvAnnotation.class))

assert builder.build() == "CREATE TEXT TABLE IF NOT EXISTS ClassWithCsvAnnotation (" +
"ID NUMERIC GENERATED ALWAYS AS IDENTITY PRIMARY KEY, " +
"name VARCHAR(255))"
}
}

2 changes: 1 addition & 1 deletion test/gstorm/metadata/ClassMetaDataAnnotationsTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ClassMetaDataAnnotationsTest extends GroovyTestCase {
void "test WithoutId"() {
ClassMetaData metadataWithId = new ClassMetaData(ClassWithoutId)

assert metadataWithId.withoutId() == true
assert metadataWithId.isWithoutId() == true
}

void "test Id should not be included in fields"() {
Expand Down
8 changes: 8 additions & 0 deletions test/models/ClassWithCsvAnnotation.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package models

import gstorm.Csv

@Csv
class ClassWithCsvAnnotation {
String name
}

0 comments on commit 641ed69

Please sign in to comment.