Hi Paolo,
these patches depend on the CObject patch you were creating earlier. My
problem is that I want to do queries with parameters that are not controlled
by me. I started to implement a Statement class (but without them being
prepared statements).
So the code is a bit better than before but still inferior to the SQLite
support. This code lacks prepared statements, lacks better binding support.
The last patch attempts to fix a type conversion of a NULL value.
regards
holger
>From 5960104e23f6ad1b2eeb5ee7f44da83a047791f9 Mon Sep 17 00:00:00 2001
From: Holger Hans Peter Freyther <[email protected]>
Date: Fri, 8 Apr 2011 11:06:52 +0200
Subject: [PATCH 1/4] dbi: Refactor and move methods to DBI.Statement
Move code from DBI.SQLite.Statement to DBI.Statement so it can
be used by a new DBI.PostgreSQL.Statement class as well.
---
packages/dbd-sqlite/ChangeLog | 4 ++++
packages/dbd-sqlite/Statement.st | 9 +--------
packages/dbi/ChangeLog | 4 ++++
packages/dbi/Statement.st | 13 ++++++++++++-
4 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/packages/dbd-sqlite/ChangeLog b/packages/dbd-sqlite/ChangeLog
index 1ee4723..31efe6c 100644
--- a/packages/dbd-sqlite/ChangeLog
+++ b/packages/dbd-sqlite/ChangeLog
@@ -1,3 +1,7 @@
+2011-04-08 Holger Peter Freyther <[email protected]>
+
+ * Statement.st: Refactor code and use DBI.Statement class>>#getCommand:.
+
2010-12-04 Paolo Bonzini <[email protected]>
* package.xml: Remove now superfluous <file> tags.
diff --git a/packages/dbd-sqlite/Statement.st b/packages/dbd-sqlite/Statement.st
index 2f455fc..68cecda 100644
--- a/packages/dbd-sqlite/Statement.st
+++ b/packages/dbd-sqlite/Statement.st
@@ -94,13 +94,6 @@ Statement subclass: SQLiteStatement [
getCommand [
<category: 'private'>
- | readStream writeStream aCharacter |
- writeStream := WriteStream on: String new.
- readStream := ReadStream on: queryString.
- readStream skipSeparators.
- [readStream atEnd
- or: [aCharacter := readStream next. aCharacter isSeparator]]
- whileFalse: [writeStream nextPut: aCharacter asUppercase].
- ^writeStream contents
+ ^ self class getCommand: queryString.
]
]
diff --git a/packages/dbi/ChangeLog b/packages/dbi/ChangeLog
index 024e8fb..67b1647 100644
--- a/packages/dbi/ChangeLog
+++ b/packages/dbi/ChangeLog
@@ -1,3 +1,7 @@
+2011-04-08 Holger Hans Peter Freyther <[email protected]>
+
+ * Statement.st: Add Statement class>>#getCommand:.
+
2010-12-04 Paolo Bonzini <[email protected]>
* package.xml: Remove now superfluous <file> tags.
diff --git a/packages/dbi/Statement.st b/packages/dbi/Statement.st
index ed216b7..e11a57b 100644
--- a/packages/dbi/Statement.st
+++ b/packages/dbi/Statement.st
@@ -8,7 +8,7 @@
"======================================================================
|
| Copyright 2006 Mike Anderson
-| Copyright 2007, 2008 Free Software Foundation, Inc.
+| Copyright 2007, 2008, 2011 Free Software Foundation, Inc.
|
| Written by Mike Anderson
|
@@ -49,6 +49,17 @@ Object subclass: Statement [
yourself
]
+ Statement class >> getCommand: queryString [
+ | readStream writeStream aCharacter |
+ writeStream := WriteStream on: String new.
+ readStream := ReadStream on: queryString.
+ readStream skipSeparators.
+ [readStream atEnd
+ or: [aCharacter := readStream next. aCharacter isSeparator]]
+ whileFalse: [writeStream nextPut: aCharacter asUppercase].
+ ^writeStream contents
+ ]
+
connection [
"Return the connection for which the statement was prepared."
--
1.7.4
>From cdafb34a2518651763b3c213bc126a41ebb24edd Mon Sep 17 00:00:00 2001
From: Holger Hans Peter Freyther <[email protected]>
Date: Fri, 8 Apr 2011 11:09:58 +0200
Subject: [PATCH 2/4] dbd-postgres: Prepare to have prepared statements in postgres
Like the SQLite driver implement Connection>>#do: and #select:
on top of the Connection>>#prepare: method. There is no functional
change right no.
---
packages/dbd-postgresql/ChangeLog | 4 ++
packages/dbd-postgresql/Connection.st | 24 ++++------
packages/dbd-postgresql/Makefile.frag | 2 +-
packages/dbd-postgresql/Statement.st | 79 +++++++++++++++++++++++++++++++++
packages/dbd-postgresql/package.xml | 1 +
5 files changed, 95 insertions(+), 15 deletions(-)
create mode 100644 packages/dbd-postgresql/Statement.st
diff --git a/packages/dbd-postgresql/ChangeLog b/packages/dbd-postgresql/ChangeLog
index 18a1e97..ea768b5 100644
--- a/packages/dbd-postgresql/ChangeLog
+++ b/packages/dbd-postgresql/ChangeLog
@@ -1,3 +1,7 @@
+2011-04-08 Holger Hans Peter Freyther <[email protected]>
+
+ * Statement.st: New.
+
2011-01-26 Stefan Schmiedl <[email protected]>
* Table.st: Take current domain into account.
diff --git a/packages/dbd-postgresql/Connection.st b/packages/dbd-postgresql/Connection.st
index 25694b8..f23d3f2 100644
--- a/packages/dbd-postgresql/Connection.st
+++ b/packages/dbd-postgresql/Connection.st
@@ -113,24 +113,20 @@ Connection subclass: PGConnection [
]
do: aSQLQuery [
- <category: 'implementations'>
- ^(PGResultSet new: (handle exec: aSQLQuery))
- checkStatusForDo;
- yourself
+ <category: 'querying'>
+ ^(self prepare: aSQLQuery) execute
]
- prepare: aSQLQuery [
- "FIXME"
-
- <category: 'implementations'>
- self notYetImplemented
+ select: aSQLQuery [
+ <category: 'querying'>
+ ^(self prepare: aSQLQuery) execute
]
- select: aSQLQuery [
- <category: 'implementations'>
- ^(PGResultSet new: (handle exec: aSQLQuery))
- checkStatusForSelect;
- yourself
+ prepare: aSQLQuery [
+ <category: 'querying'>
+ ^(PGStatement on: self)
+ dbHandle: handle;
+ queryString: aSQLQuery.
]
close [
diff --git a/packages/dbd-postgresql/Makefile.frag b/packages/dbd-postgresql/Makefile.frag
index 6991183..3479b44 100644
--- a/packages/dbd-postgresql/Makefile.frag
+++ b/packages/dbd-postgresql/Makefile.frag
@@ -1,5 +1,5 @@
DBD-PostgreSQL_FILES = \
-packages/dbd-postgresql/Connection.st packages/dbd-postgresql/ResultSet.st packages/dbd-postgresql/Row.st packages/dbd-postgresql/ColumnInfo.st packages/dbd-postgresql/Table.st packages/dbd-postgresql/TableColumnInfo.st packages/dbd-postgresql/FieldConverter.st
+packages/dbd-postgresql/Connection.st packages/dbd-postgresql/ResultSet.st packages/dbd-postgresql/Row.st packages/dbd-postgresql/ColumnInfo.st packages/dbd-postgresql/Statement.st packages/dbd-postgresql/Table.st packages/dbd-postgresql/TableColumnInfo.st packages/dbd-postgresql/FieldConverter.st
$(DBD-PostgreSQL_FILES):
$(srcdir)/packages/dbd-postgresql/stamp-classes: $(DBD-PostgreSQL_FILES)
touch $(srcdir)/packages/dbd-postgresql/stamp-classes
diff --git a/packages/dbd-postgresql/Statement.st b/packages/dbd-postgresql/Statement.st
new file mode 100644
index 0000000..c9cfaa7
--- /dev/null
+++ b/packages/dbd-postgresql/Statement.st
@@ -0,0 +1,79 @@
+"======================================================================
+|
+| PostgreSQL bindings, Statement class
+|
+|
+ ======================================================================"
+
+
+"======================================================================
+|
+| Copyright 2011 Free Software Foundation, Inc.
+| Written by Holger Hans Peter Freyther
+|
+| This file is part of the GNU Smalltalk class library.
+|
+| The GNU Smalltalk class library is free software; you can redistribute it
+| and/or modify it under the terms of the GNU Lesser General Public License
+| as published by the Free Software Foundation; either version 2.1, or (at
+| your option) any later version.
+|
+| The GNU Smalltalk class library is distributed in the hope that it will be
+| useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+| General Public License for more details.
+|
+| You should have received a copy of the GNU Lesser General Public License
+| along with the GNU Smalltalk class library; see the file COPYING.LIB.
+| If not, write to the Free Software Foundation, 59 Temple Place - Suite
+| 330, Boston, MA 02110-1301, USA.
+|
+ ======================================================================
+"
+
+
+Statement subclass: PGStatement [
+ | dbHandle queryString isSelect |
+
+ <category: 'DBI-Drivers'>
+ <comment: 'I represent a Postgres prepared statement. Or actually right
+now the ability to execute commands with binding.'>
+
+ SelectQueries := #('EXPLAIN' 'SELECT') asSet.
+
+ dbHandle: aHandle [
+ <category: 'private'>
+ dbHandle := aHandle.
+ ]
+
+ queryString [
+ <category: 'accessing'>
+ ^queryString
+ ]
+
+ queryString: aSQLQuery [
+ <category: 'accessing'>
+ queryString := aSQLQuery.
+ ]
+
+ isSelect [
+ <category: 'accessing'>
+ isSelect isNil
+ ifTrue: [isSelect := SelectQueries includes: (self class getCommand: queryString)].
+ ^isSelect
+ ]
+
+ execute [
+ <category: 'querying'>
+ | res |
+ res := PGResultSet new: (dbHandle exec: queryString).
+ self isSelect
+ ifTrue: [res checkStatusForSelect]
+ ifFalse: [res checkStatusForDo].
+ ^ res
+ ]
+
+ executeWithAll: aParams [
+ self notYetImplemented
+ ]
+]
diff --git a/packages/dbd-postgresql/package.xml b/packages/dbd-postgresql/package.xml
index b1a336e..36d6a29 100644
--- a/packages/dbd-postgresql/package.xml
+++ b/packages/dbd-postgresql/package.xml
@@ -8,6 +8,7 @@
<filein>ResultSet.st</filein>
<filein>Row.st</filein>
<filein>ColumnInfo.st</filein>
+ <filein>Statement.st</filein>
<filein>Table.st</filein>
<filein>TableColumnInfo.st</filein>
<filein>FieldConverter.st</filein>
--
1.7.4
>From 20aeb9470d783dd827147136e530fca23cd9810d Mon Sep 17 00:00:00 2001
From: Holger Hans Peter Freyther <[email protected]>
Date: Fri, 8 Apr 2011 14:09:37 +0200
Subject: [PATCH 3/4] dbd-postgres: Allow to execute queries with parameters
This only supports the PostgreSQL way of specifying parameters
using the $1 $2 $3 parameters. It does not support named bindings
or such. This makes going from SQLite to Postgres a lot harder. The
parameters must be provided as string, there is no type conversion
done on this level.
---
packages/dbd-postgresql/ChangeLog | 5 ++++
packages/dbd-postgresql/Connection.st | 38 +++++++++++++++++++++++++++++++++
packages/dbd-postgresql/Statement.st | 21 +++++++++++++----
3 files changed, 59 insertions(+), 5 deletions(-)
diff --git a/packages/dbd-postgresql/ChangeLog b/packages/dbd-postgresql/ChangeLog
index ea768b5..0ca6d3b 100644
--- a/packages/dbd-postgresql/ChangeLog
+++ b/packages/dbd-postgresql/ChangeLog
@@ -1,5 +1,10 @@
2011-04-08 Holger Hans Peter Freyther <[email protected]>
+ * Statements.st: Implement executeWithAll:
+ * Connection.st: Invoke PQexecParams.
+
+2011-04-08 Holger Hans Peter Freyther <[email protected]>
+
* Statement.st: New.
2011-01-26 Stefan Schmiedl <[email protected]>
diff --git a/packages/dbd-postgresql/Connection.st b/packages/dbd-postgresql/Connection.st
index f23d3f2..202e604 100644
--- a/packages/dbd-postgresql/Connection.st
+++ b/packages/dbd-postgresql/Connection.st
@@ -188,6 +188,44 @@ CObject subclass: PQConnection [
exec: aSqlStatement [
<cCall: 'PQexec' returning: #{PQResultSet} args: #(#self #string)>
]
+
+ "Executing SQL with params"
+ exec: aSqlStatement with: params [
+ | par |
+
+ "Sanity check before we do memory allocations in C"
+ (params allSatisfy: [:el | el isString]) ifFalse: [
+ ^ self error: 'All parameters must be strings here'].
+
+ "Convert the params into an array of C-Strings."
+ par := CStringType new: params size.
+ 1 to: params size do: [:each |
+ par at: each - 1 put: (params at: each)].
+
+ [^ self
+ exec_params:aSqlStatement
+ n_par: params size
+ types: nil
+ values: par
+ lengths: nil
+ formats: nil
+ res: 0
+ ] ensure: [
+ "Free the memory we allocated"
+
+ 0 to: params size - 1 do: [:each |
+ (par derefAt: (each * CStringType sizeof) type: CObjectType) free
+ ].
+
+ par free.
+ ]
+ ]
+
+ exec_params: cmd n_par: parAms types: types values: vals lengths: l formats: f res: r [
+ <category: 'private'>
+ <cCall: 'PQexecParams' returning: #{PQResultSet}
+ args: #(#self #string #int #cObject #cObject #cObject #cObject #int)>
+ ]
]
diff --git a/packages/dbd-postgresql/Statement.st b/packages/dbd-postgresql/Statement.st
index c9cfaa7..9335989 100644
--- a/packages/dbd-postgresql/Statement.st
+++ b/packages/dbd-postgresql/Statement.st
@@ -53,6 +53,8 @@ now the ability to execute commands with binding.'>
queryString: aSQLQuery [
<category: 'accessing'>
+ "In PostgreSQL one can use $1 for binding parameters with the
+ executeWithAll:. The parameters must be all strings."
queryString := aSQLQuery.
]
@@ -63,17 +65,26 @@ now the ability to execute commands with binding.'>
^isSelect
]
+ checkResult: aRes [
+ <category: 'private'>
+ self isSelect
+ ifTrue: [aRes checkStatusForSelect]
+ ifFalse: [aRes checkStatusForDo].
+ ^ aRes
+ ]
+
execute [
<category: 'querying'>
| res |
res := PGResultSet new: (dbHandle exec: queryString).
- self isSelect
- ifTrue: [res checkStatusForSelect]
- ifFalse: [res checkStatusForDo].
- ^ res
+ ^ self checkResult: res.
]
executeWithAll: aParams [
- self notYetImplemented
+ | res |
+ "In PostgreSQL one can use $1 for binding parameters with the
+ executeWithAll:. The parameters must be all strings."
+ res := PGResultSet new: (dbHandle exec: queryString with: aParams).
+ ^ self checkResult: res.
]
]
--
1.7.4
>From 85de709a47474634524c3492a9927a53065b1eae Mon Sep 17 00:00:00 2001
From: Holger Hans Peter Freyther <[email protected]>
Date: Fri, 8 Apr 2011 10:35:13 +0200
Subject: [PATCH 4/4] dbd-postgres: Do not attempt to the NULL value
If the value of a column is NULL the closest Smalltalk type
is nil. Do not attempt to create any instance from a NULL.
---
packages/dbd-postgresql/ChangeLog | 4 ++++
packages/dbd-postgresql/ColumnInfo.st | 3 ++-
2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/packages/dbd-postgresql/ChangeLog b/packages/dbd-postgresql/ChangeLog
index 0ca6d3b..295b594 100644
--- a/packages/dbd-postgresql/ChangeLog
+++ b/packages/dbd-postgresql/ChangeLog
@@ -1,3 +1,7 @@
+2011-04-07 Holger Hans Peter Freyther <[email protected]>
+
+ * ColumnInfo.st: Do not attempt to convert a NULL value.
+
2011-04-08 Holger Hans Peter Freyther <[email protected]>
* Statements.st: Implement executeWithAll:
diff --git a/packages/dbd-postgresql/ColumnInfo.st b/packages/dbd-postgresql/ColumnInfo.st
index 436ccbd..74c5343 100644
--- a/packages/dbd-postgresql/ColumnInfo.st
+++ b/packages/dbd-postgresql/ColumnInfo.st
@@ -213,7 +213,8 @@ ColumnInfo subclass: PGColumnInfo [
PGColumnInfo class >> convert: aRaw type: aType [
<category: 'type conversions'>
- TypeConversions at: aType ifPresent: [:sel | ^self perform: sel with: aRaw].
+ aRaw isNil ifFalse: [
+ TypeConversions at: aType ifPresent: [:sel | ^self perform: sel with: aRaw]].
^aRaw
]
--
1.7.4
_______________________________________________
help-smalltalk mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/help-smalltalk