From 882775d0205643eef6d32920e02cbe73cb3dc1a3 Mon Sep 17 00:00:00 2001 From: King-Ozymandias Date: Wed, 4 Sep 2024 20:47:35 +0200 Subject: [PATCH] Unification of writing. Also, the "mapping" version doesn't copy rows out of the dataframe. --- README.md | 6 +- .../DataFrame.extension.st | 4 +- .../DataFrameAbstractSqliteWriter.class.st | 35 -------- ...ataFrameSqliteColumnMappingWriter.class.st | 57 ------------- .../DataFrameSqliteWriter.class.st | 85 ++++++++++++++----- 5 files changed, 69 insertions(+), 118 deletions(-) delete mode 100644 src/DataFrame-IO-Sqlite/DataFrameAbstractSqliteWriter.class.st delete mode 100644 src/DataFrame-IO-Sqlite/DataFrameSqliteColumnMappingWriter.class.st diff --git a/README.md b/README.md index a4dda6f0..f054d67c 100644 --- a/README.md +++ b/README.md @@ -140,11 +140,7 @@ df := DataFrame readFromSqliteCursor: (conn execute: 'SELECT * FROM table'). ```st df writeToSqlite: conn tableName: 'table'. ``` -#### Write to differently named colums (provide names for ALL DataFrame columns!) -```st -df writeToSqlite: conn tableName: 'table' columnNames: #('col1' 'col2' 'col3'). -``` -#### Mapping (selecting / renaming dataframe columns): +#### Selecting / renaming dataframe columns: Let's assume: - CREATE TABLE tbl (a,b,c) - DataFrame with columns (a,x,c,d) diff --git a/src/DataFrame-IO-Sqlite/DataFrame.extension.st b/src/DataFrame-IO-Sqlite/DataFrame.extension.st index dd910be6..de8dacef 100644 --- a/src/DataFrame-IO-Sqlite/DataFrame.extension.st +++ b/src/DataFrame-IO-Sqlite/DataFrame.extension.st @@ -18,7 +18,7 @@ DataFrame >> writeToSqlite: aSqlite3Connection tableName: aString [ DataFrame >> writeToSqlite: aSqlite3Connection tableName: aString columnMappings: aCollection [ | writer | - writer := DataFrameSqliteColumnMappingWriter + writer := DataFrameSqliteWriter writeToTable: aString columnMappings: aCollection. self writeTo: aSqlite3Connection using: writer @@ -30,6 +30,6 @@ DataFrame >> writeToSqlite: aSqlite3Connection tableName: aString columnNames: a | writer | writer := DataFrameSqliteWriter writeToTable: aString - columnNames: aCollection. + columnMappings: aCollection. self writeTo: aSqlite3Connection using: writer ] diff --git a/src/DataFrame-IO-Sqlite/DataFrameAbstractSqliteWriter.class.st b/src/DataFrame-IO-Sqlite/DataFrameAbstractSqliteWriter.class.st deleted file mode 100644 index bb8a94c7..00000000 --- a/src/DataFrame-IO-Sqlite/DataFrameAbstractSqliteWriter.class.st +++ /dev/null @@ -1,35 +0,0 @@ -Class { - #name : 'DataFrameAbstractSqliteWriter', - #superclass : 'DataFrameWriter', - #instVars : [ - 'tableName' - ], - #category : 'DataFrame-IO-Sqlite', - #package : 'DataFrame-IO-Sqlite' -} - -{ #category : 'helpers' } -DataFrameAbstractSqliteWriter >> insertQueryForColumns: aSequence [ - "" - ^ String streamContents: [ :strm | - strm - nextPutAll: 'INSERT INTO '; - nextPutAll: tableName; - nextPut: $(; - nextPutAll: (',' join: aSequence); - nextPutAll: ')VALUES('. - aSequence do: [ :ignore | strm nextPut: $? ] separatedBy: [ strm nextPut: $, ]. - strm nextPut: $) ] -] - -{ #category : 'accessing' } -DataFrameAbstractSqliteWriter >> tableName [ - - ^ tableName -] - -{ #category : 'accessing' } -DataFrameAbstractSqliteWriter >> tableName: anObject [ - - tableName := anObject -] diff --git a/src/DataFrame-IO-Sqlite/DataFrameSqliteColumnMappingWriter.class.st b/src/DataFrame-IO-Sqlite/DataFrameSqliteColumnMappingWriter.class.st deleted file mode 100644 index b7912bc5..00000000 --- a/src/DataFrame-IO-Sqlite/DataFrameSqliteColumnMappingWriter.class.st +++ /dev/null @@ -1,57 +0,0 @@ -Class { - #name : 'DataFrameSqliteColumnMappingWriter', - #superclass : 'DataFrameAbstractSqliteWriter', - #instVars : [ - 'columnMappings' - ], - #category : 'DataFrame-IO-Sqlite', - #package : 'DataFrame-IO-Sqlite' -} - -{ #category : 'writing' } -DataFrameSqliteColumnMappingWriter class >> writeToTable: aString columnMappings: aCollection [ - - ^ self new - tableName: aString; - columnMappings: aCollection; - yourself -] - -{ #category : 'accessing' } -DataFrameSqliteColumnMappingWriter >> columnMappings [ - - ^ columnMappings -] - -{ #category : 'accessing' } -DataFrameSqliteColumnMappingWriter >> columnMappings: anObject [ - - columnMappings := anObject -] - -{ #category : 'helpers' } -DataFrameSqliteColumnMappingWriter >> fieldIndicesFor: aDataFrame [ - "gather indices of columns in dataframe (to avoid lookup by field name later, in loop)" - - ^ columnMappings collect: [ :m | - | sourceName | - sourceName := m isAssociation - ifTrue: [ m key ] - ifFalse: [ m ]. - aDataFrame columnNames indexOf: sourceName ] -] - -{ #category : 'writing' } -DataFrameSqliteColumnMappingWriter >> write: aDataFrame to: aSqliteConnection [ - - | fieldIndices args stmt | - fieldIndices := self fieldIndicesFor: aDataFrame. - args := Array new: fieldIndices size. - stmt := aSqliteConnection prepare: (self insertQueryForColumns: - (columnMappings collect: [ :m | m value ])). - - 1 to: aDataFrame dimensions x do: [ :rowIndex | - fieldIndices withIndexDo: [ :srcCol :dstCol | - args at: dstCol put: (aDataFrame contents at: rowIndex at: srcCol) ]. - stmt execute: args ] -] diff --git a/src/DataFrame-IO-Sqlite/DataFrameSqliteWriter.class.st b/src/DataFrame-IO-Sqlite/DataFrameSqliteWriter.class.st index 4e5c7ccb..ca167f92 100644 --- a/src/DataFrame-IO-Sqlite/DataFrameSqliteWriter.class.st +++ b/src/DataFrame-IO-Sqlite/DataFrameSqliteWriter.class.st @@ -1,14 +1,15 @@ Class { #name : 'DataFrameSqliteWriter', - #superclass : 'DataFrameAbstractSqliteWriter', + #superclass : 'DataFrameWriter', #instVars : [ - 'columnNames' + 'tableName', + 'columnMappings' ], #category : 'DataFrame-IO-Sqlite', #package : 'DataFrame-IO-Sqlite' } -{ #category : 'instance creation' } +{ #category : 'writing' } DataFrameSqliteWriter class >> writeToTable: aString [ ^ self new @@ -16,43 +17,89 @@ DataFrameSqliteWriter class >> writeToTable: aString [ yourself ] -{ #category : 'instance creation' } -DataFrameSqliteWriter class >> writeToTable: aString columnNames: aCollection [ +{ #category : 'writing' } +DataFrameSqliteWriter class >> writeToTable: aString columnMappings: aCollection [ ^ self new tableName: aString; - columnNames: aCollection; + columnMappings: aCollection; yourself ] { #category : 'accessing' } -DataFrameSqliteWriter >> columnNames [ +DataFrameSqliteWriter >> columnMappings [ - ^ columnNames + ^ columnMappings ] { #category : 'accessing' } -DataFrameSqliteWriter >> columnNames: anObject [ +DataFrameSqliteWriter >> columnMappings: anObject [ + + columnMappings := anObject +] + +{ #category : 'helpers' } +DataFrameSqliteWriter >> fieldIndicesFor: aDataFrame [ + "gather indices of columns in dataframe (to avoid lookup by field name later, in loop)" + + ^ (self getColumnMappings: aDataFrame) collect: [ :m | + | sourceName | + sourceName := m isAssociation + ifTrue: [ m key ] + ifFalse: [ m ]. + aDataFrame columnNames indexOf: sourceName ] +] + +{ #category : 'helpers' } +DataFrameSqliteWriter >> getColumnMappings: aDataFrame [ + + ^ columnMappings ifNil: [ aDataFrame columnNames ] +] + +{ #category : 'helpers' } +DataFrameSqliteWriter >> getColumnNames: aDataFrame [ - columnNames := anObject + ^ (self getColumnMappings: aDataFrame) collect: [ :m | m value ] ] { #category : 'helpers' } -DataFrameSqliteWriter >> getColumnNamesFor: aDataFrame [ +DataFrameSqliteWriter >> insertQueryForColumns: aSequence [ + "" + ^ String streamContents: [ :strm | + strm + nextPutAll: 'INSERT INTO '; + nextPutAll: tableName; + nextPut: $(; + nextPutAll: (',' join: aSequence); + nextPutAll: ')VALUES('. + aSequence do: [ :ignore | strm nextPut: $? ] separatedBy: [ strm nextPut: $, ]. + strm nextPut: $) ] +] + +{ #category : 'accessing' } +DataFrameSqliteWriter >> tableName [ - columnNames ifNil: [ ^ aDataFrame columnNames ]. - columnNames size ~= aDataFrame columns size ifTrue: [ - self error: - 'Column count mismatch (Writer columns <=> DataFrame columns)' ]. - ^ columnNames + ^ tableName +] + +{ #category : 'accessing' } +DataFrameSqliteWriter >> tableName: anObject [ + + tableName := anObject ] { #category : 'writing' } DataFrameSqliteWriter >> write: aDataFrame to: aSqliteConnection [ - | stmt | + | fieldIndices args stmt | + fieldIndices := self fieldIndicesFor: aDataFrame. + args := Array new: fieldIndices size. stmt := aSqliteConnection prepare: (self insertQueryForColumns: - (self getColumnNamesFor: aDataFrame)). - aDataFrame do: [ :row | stmt execute: row asArray ] + (self getColumnNames: aDataFrame)). + + 1 to: aDataFrame dimensions x do: [ :rowIndex | + fieldIndices withIndexDo: [ :srcCol :dstCol | + args at: dstCol put: (aDataFrame contents at: rowIndex at: srcCol) ]. + stmt execute: args ] ]