Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: infer initial schema #79

Merged
merged 5 commits into from
Jun 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DSL/com.larsreimann.safeds/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ dependencies {
api(platform("org.eclipse.xtext:xtext-dev-bom:$xtextVersion"))
implementation("org.eclipse.xtext:org.eclipse.xtext:$xtextVersion")

implementation("tech.tablesaw:tablesaw-core:0.43.1")

testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.8.2")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.larsreimann.safeds.staticAnalysis.schema

import com.larsreimann.safeds.emf.createSdsColumn
import com.larsreimann.safeds.emf.createSdsNamedType
import com.larsreimann.safeds.emf.createSdsSchema
import com.larsreimann.safeds.emf.createSdsString
import com.larsreimann.safeds.safeDS.SdsColumn
import com.larsreimann.safeds.safeDS.SdsSchema
import com.larsreimann.safeds.stdlibAccess.StdlibClasses
import com.larsreimann.safeds.stdlibAccess.getStdlibClassOrNull
import org.eclipse.emf.ecore.EObject
import org.eclipse.xtext.naming.QualifiedName
import tech.tablesaw.api.Table

fun inferInitialSchema(context: EObject, name: String, path: String): SdsSchema? {
try {
var colList: List<SdsColumn> = emptyList()

val table = Table.read().csv(path)

for (row in table.structure()) {
val colName = row.getString(1)
val colType = row.getString(2)
val colQualifiedName: QualifiedName = when (colType) {
"DOUBLE" -> StdlibClasses.Float
"STRING" -> StdlibClasses.String
"INTEGER" -> StdlibClasses.Int
"BOOLEAN" -> StdlibClasses.Boolean
else -> StdlibClasses.Any
}

val stdlibClass = context.getStdlibClassOrNull(colQualifiedName) ?: return null

colList += createSdsColumn(
createSdsString(colName),
createSdsNamedType(stdlibClass, isNullable = true)
)
}

return createSdsSchema(name, columns = colList)
} catch (e: IllegalStateException) {
return null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.larsreimann.safeds.staticAnalysis.schema

import com.google.inject.Inject
import com.larsreimann.safeds.constant.SdsFileExtension
import com.larsreimann.safeds.emf.createSdsCompilationUnit
import com.larsreimann.safeds.emf.createSdsDummyResource
import com.larsreimann.safeds.serializer.SerializationResult
import com.larsreimann.safeds.serializer.serializeToFormattedString
import com.larsreimann.safeds.testing.ParseHelper
import com.larsreimann.safeds.testing.SafeDSInjectorProvider
import com.larsreimann.safeds.testing.getResourcePath
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeInstanceOf
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.extensions.InjectionExtension
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith

@ExtendWith(InjectionExtension::class)
@InjectWith(SafeDSInjectorProvider::class)
class InitialSchemaInferenceTest {

@Inject
private lateinit var parseHelper: ParseHelper

private val expectedSchema = """
|package test
|
|schema TestSchema {
| "Column0" : Int?,
| "Column1" : Int?,
| "Column2" : Int?,
| "Column3" : String?,
| "Column4" : String?,
| "Column5" : Int?,
| "Column6" : Int?,
| "Column7" : Int?,
| "Column8" : String?,
| "Column9" : Float?,
| "Column10" : String?,
| "Column11" : String?
|}
""".trimMargin()

@Test
fun inferInitialSchema() {
val context = parseHelper.parseProgramText("package test")
context.shouldNotBeNull()

val csvPath = javaClass.classLoader.getResourcePath("schema/dummyData.csv").toString()
val schema = inferInitialSchema(context, "TestSchema", csvPath)

schema.shouldNotBeNull()

val compilationUnit = createSdsCompilationUnit(packageName = "test", members = listOf(schema))
createSdsDummyResource("test", SdsFileExtension.Schema, compilationUnit)

val result = compilationUnit.serializeToFormattedString()
result.shouldBeInstanceOf<SerializationResult.Success>()

result.code.shouldBe(expectedSchema)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Column0,Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8,Column9,Column10,Column11
1,0,3,asdfsdf,male,22,1,0,rhtyy,7.25,,S
2,1,1,asdfgfdghhfg,male,38,1,0,ewrterwt,71.2833,C85,C
3,1,3,ertewrtwer,male,26,0,0,vcdfgre,7.925,,S
4,1,1,qwerwqerwe,male,35,1,0,sfewrtret,53.1,C123,S