first version of postgres backend
authorMarcus Eggenberger <egs@quassel-irc.org>
Sat, 21 Feb 2009 15:47:18 +0000 (16:47 +0100)
committerMarcus Eggenberger <egs@quassel-irc.org>
Tue, 3 Mar 2009 19:57:04 +0000 (20:57 +0100)
86 files changed:
src/core/CMakeLists.txt
src/core/SQL/PostgreSQL/14/delete_backlog_by_uid.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_backlog_for_buffer.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_backlog_for_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_buffer_for_bufferid.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_buffers_by_uid.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_buffers_for_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_identity.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_ircservers_for_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_networks_by_uid.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_nicks.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/delete_quasseluser.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_buffer.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_identity.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_message.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_nick.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_quasseluser.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_sender.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_server.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/insert_user_setting.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_authuser.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_bufferByName.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_bufferExists.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_buffer_by_id.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_buffer_lastseen_messages.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_buffers.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_buffers_for_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_checkidentity.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_connected_networks.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_identities.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_internaluser.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_messages.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_messagesAll.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_messagesAllNew.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_messagesNewerThan.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_messagesNewestK.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_networkExists.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_network_awaymsg.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_network_usermode.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_networks_for_user.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_nicks.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_persistent_channels.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_servers_for_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_user_setting.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/select_userid.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_000_quasseluser.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_010_sender.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_020_identity.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_030_identity_nick.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_040_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_050_buffer.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_060_backlog.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_070_coreinfo.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_080_ircservers.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_090_backlog_idx.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/setup_100_user_setting.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_backlog_bufferid.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_buffer_lastseen.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_buffer_name.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_buffer_persistent_channel.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_buffer_set_channel_key.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_identity.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_network.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_network_connected.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_network_set_awaymsg.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_network_set_usermode.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_user_setting.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_username.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/14/update_userpassword.sql [new file with mode: 0644]
src/core/abstractsqlstorage.cpp
src/core/abstractsqlstorage.h
src/core/core.cpp
src/core/core.h
src/core/coreapplication.cpp
src/core/corenetwork.cpp
src/core/coresession.cpp
src/core/postgresqlstorage.cpp [new file with mode: 0644]
src/core/postgresqlstorage.h [new file with mode: 0644]
src/core/sql.qrc
src/core/sqlitestorage.h
src/core/storage.h
src/qtui/coreconfigwizard.cpp
src/qtui/coreconfigwizard.h
src/qtui/ui/coreconfigwizardstorageselectionpage.ui

index e0e2044..1713760 100644 (file)
@@ -26,6 +26,7 @@ set(SOURCES
     coreusersettings.cpp
     ctcphandler.cpp
     ircserverhandler.cpp
     coreusersettings.cpp
     ctcphandler.cpp
     ircserverhandler.cpp
+    postgresqlstorage.cpp
     sessionthread.cpp
     sqlitestorage.cpp
     storage.cpp
     sessionthread.cpp
     sqlitestorage.cpp
     storage.cpp
@@ -49,6 +50,7 @@ set(MOC_HDRS
     coresession.h
     ctcphandler.h
     ircserverhandler.h
     coresession.h
     ctcphandler.h
     ircserverhandler.h
+    postgresqlstorage.h
     sqlitestorage.h
     storage.h
     sessionthread.h
     sqlitestorage.h
     storage.h
     sessionthread.h
diff --git a/src/core/SQL/PostgreSQL/14/delete_backlog_by_uid.sql b/src/core/SQL/PostgreSQL/14/delete_backlog_by_uid.sql
new file mode 100644 (file)
index 0000000..b5520ec
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM backlog
+WHERE bufferid IN (SELECT DISTINCT bufferid FROM buffer WHERE userid = :userid)
diff --git a/src/core/SQL/PostgreSQL/14/delete_backlog_for_buffer.sql b/src/core/SQL/PostgreSQL/14/delete_backlog_for_buffer.sql
new file mode 100644 (file)
index 0000000..38bf564
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM backlog
+WHERE bufferid = :bufferid
diff --git a/src/core/SQL/PostgreSQL/14/delete_backlog_for_network.sql b/src/core/SQL/PostgreSQL/14/delete_backlog_for_network.sql
new file mode 100644 (file)
index 0000000..07a893f
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM backlog
+WHERE bufferid IN (SELECT bufferid FROM buffer WHERE networkid = :networkid)
diff --git a/src/core/SQL/PostgreSQL/14/delete_buffer_for_bufferid.sql b/src/core/SQL/PostgreSQL/14/delete_buffer_for_bufferid.sql
new file mode 100644 (file)
index 0000000..91dfeb9
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM buffer
+WHERE bufferid = :bufferid
diff --git a/src/core/SQL/PostgreSQL/14/delete_buffers_by_uid.sql b/src/core/SQL/PostgreSQL/14/delete_buffers_by_uid.sql
new file mode 100644 (file)
index 0000000..14f56ac
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM buffer
+WHERE userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/delete_buffers_for_network.sql b/src/core/SQL/PostgreSQL/14/delete_buffers_for_network.sql
new file mode 100644 (file)
index 0000000..9b9ccdb
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM buffer
+WHERE networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/delete_identity.sql b/src/core/SQL/PostgreSQL/14/delete_identity.sql
new file mode 100644 (file)
index 0000000..7d25c0e
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM identity
+WHERE identityid = :identityid AND userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/delete_ircservers_for_network.sql b/src/core/SQL/PostgreSQL/14/delete_ircservers_for_network.sql
new file mode 100644 (file)
index 0000000..c74e597
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM ircserver
+WHERE networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/delete_network.sql b/src/core/SQL/PostgreSQL/14/delete_network.sql
new file mode 100644 (file)
index 0000000..7200ee4
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM network
+WHERE networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/delete_networks_by_uid.sql b/src/core/SQL/PostgreSQL/14/delete_networks_by_uid.sql
new file mode 100644 (file)
index 0000000..0542d85
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM network
+WHERE userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/delete_nicks.sql b/src/core/SQL/PostgreSQL/14/delete_nicks.sql
new file mode 100644 (file)
index 0000000..8aac599
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM identity_nick
+WHERE identityid = :identityid;
diff --git a/src/core/SQL/PostgreSQL/14/delete_quasseluser.sql b/src/core/SQL/PostgreSQL/14/delete_quasseluser.sql
new file mode 100644 (file)
index 0000000..f9bc9ae
--- /dev/null
@@ -0,0 +1,2 @@
+DELETE FROM quasseluser
+WHERE userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/insert_buffer.sql b/src/core/SQL/PostgreSQL/14/insert_buffer.sql
new file mode 100644 (file)
index 0000000..e3dd6aa
--- /dev/null
@@ -0,0 +1,3 @@
+INSERT INTO buffer (userid, networkid, buffername, buffercname, buffertype)
+VALUES (:userid, :networkid, :buffername, :buffercname, :buffertype)
+RETURNING bufferid
diff --git a/src/core/SQL/PostgreSQL/14/insert_identity.sql b/src/core/SQL/PostgreSQL/14/insert_identity.sql
new file mode 100644 (file)
index 0000000..6318268
--- /dev/null
@@ -0,0 +1,3 @@
+INSERT INTO identity (userid, identityname, realname, awaynick, awaynickenabled, awayreason, awayreasonenabled, autoawayenabled, autoawaytime, autoawayreason, autoawayreasonenabled, detachawayenabled, detachawayreason, detachawayreasonenabled, ident, kickreason, partreason, quitreason, sslcert, sslkey)
+VALUES (:userid, :identityname, :realname, :awaynick, :awaynickenabled, :awayreason, :awayreasonenabled, :autoawayenabled, :autoawaytime, :autoawayreason, :autoawayreasonenabled, :detachawayenabled, :detachawayreason, :detachawayreasonenabled, :ident, :kickreason, :partreason, :quitreason, :sslcert, :sslkey)
+RETURNING identityid
diff --git a/src/core/SQL/PostgreSQL/14/insert_message.sql b/src/core/SQL/PostgreSQL/14/insert_message.sql
new file mode 100644 (file)
index 0000000..867f066
--- /dev/null
@@ -0,0 +1,3 @@
+INSERT INTO backlog (time, bufferid, type, flags, senderid, message)
+VALUES (:time, :bufferid, :type, :flags, (SELECT senderid FROM sender WHERE sender = :sender), :message)
+RETURNING messageid
diff --git a/src/core/SQL/PostgreSQL/14/insert_network.sql b/src/core/SQL/PostgreSQL/14/insert_network.sql
new file mode 100644 (file)
index 0000000..4f94b43
--- /dev/null
@@ -0,0 +1,3 @@
+INSERT INTO network (userid, networkname, identityid, servercodec, encodingcodec, decodingcodec, userandomserver, perform, useautoidentify, autoidentifyservice, autoidentifypassword, useautoreconnect, autoreconnectinterval, autoreconnectretries, unlimitedconnectretries, rejoinchannels)
+VALUES (:userid, :networkname, :identityid, :servercodec, :encodingcodec, :decodingcodec, :userandomserver, :perform, :useautoidentify, :autoidentifyservice, :autoidentifypassword, :useautoreconnect, :autoreconnectinterval, :autoreconnectretries, :unlimitedconnectretries, :rejoinchannels)
+RETURNING networkid
diff --git a/src/core/SQL/PostgreSQL/14/insert_nick.sql b/src/core/SQL/PostgreSQL/14/insert_nick.sql
new file mode 100644 (file)
index 0000000..331da3c
--- /dev/null
@@ -0,0 +1,2 @@
+INSERT INTO identity_nick (identityid, nick)
+VALUES (:identityid, :nick)
diff --git a/src/core/SQL/PostgreSQL/14/insert_quasseluser.sql b/src/core/SQL/PostgreSQL/14/insert_quasseluser.sql
new file mode 100644 (file)
index 0000000..f336d0c
--- /dev/null
@@ -0,0 +1,3 @@
+INSERT INTO quasseluser (username, password)
+VALUES (:username, :password)
+RETURNING userid
diff --git a/src/core/SQL/PostgreSQL/14/insert_sender.sql b/src/core/SQL/PostgreSQL/14/insert_sender.sql
new file mode 100644 (file)
index 0000000..0e84f63
--- /dev/null
@@ -0,0 +1,2 @@
+INSERT INTO sender (sender)
+VALUES (:sender)
\ No newline at end of file
diff --git a/src/core/SQL/PostgreSQL/14/insert_server.sql b/src/core/SQL/PostgreSQL/14/insert_server.sql
new file mode 100644 (file)
index 0000000..d9605eb
--- /dev/null
@@ -0,0 +1,2 @@
+INSERT INTO ircserver (userid, networkid, hostname, port, password, ssl, sslversion, useproxy, proxytype, proxyhost, proxyport, proxyuser, proxypass)
+VALUES (:userid, :networkid, :hostname, :port, :password, :ssl, :sslversion, :useproxy, :proxytype, :proxyhost, :proxyport, :proxyuser, :proxypass)
diff --git a/src/core/SQL/PostgreSQL/14/insert_user_setting.sql b/src/core/SQL/PostgreSQL/14/insert_user_setting.sql
new file mode 100644 (file)
index 0000000..f85d340
--- /dev/null
@@ -0,0 +1,2 @@
+INSERT INTO user_setting (userid, settingname, settingvalue)
+VALUES (:userid, :settingname, :settingvalue)
diff --git a/src/core/SQL/PostgreSQL/14/select_authuser.sql b/src/core/SQL/PostgreSQL/14/select_authuser.sql
new file mode 100644 (file)
index 0000000..f11bf18
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT userid
+FROM quasseluser
+WHERE username = :username AND password = :password
diff --git a/src/core/SQL/PostgreSQL/14/select_bufferByName.sql b/src/core/SQL/PostgreSQL/14/select_bufferByName.sql
new file mode 100644 (file)
index 0000000..79febdb
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT bufferid, buffertype, groupid
+FROM buffer
+WHERE networkid = :networkid AND userid = :userid AND buffercname = :buffercname
diff --git a/src/core/SQL/PostgreSQL/14/select_bufferExists.sql b/src/core/SQL/PostgreSQL/14/select_bufferExists.sql
new file mode 100644 (file)
index 0000000..47caae1
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT bufferid
+FROM buffer
+WHERE userid = :userid AND bufferid = :bufferid
diff --git a/src/core/SQL/PostgreSQL/14/select_buffer_by_id.sql b/src/core/SQL/PostgreSQL/14/select_buffer_by_id.sql
new file mode 100644 (file)
index 0000000..09f202e
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT bufferid, networkid, buffertype, groupid, buffername
+FROM buffer
+WHERE bufferid = :bufferid
diff --git a/src/core/SQL/PostgreSQL/14/select_buffer_lastseen_messages.sql b/src/core/SQL/PostgreSQL/14/select_buffer_lastseen_messages.sql
new file mode 100644 (file)
index 0000000..d3a0ecc
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT bufferid, lastseenmsgid
+FROM buffer
+WHERE userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/select_buffers.sql b/src/core/SQL/PostgreSQL/14/select_buffers.sql
new file mode 100644 (file)
index 0000000..2bea9c8
--- /dev/null
@@ -0,0 +1,4 @@
+SELECT DISTINCT buffer.bufferid, network.networkid, buffertype, groupid, buffername
+FROM buffer
+JOIN network ON buffer.networkid = network.networkid
+WHERE buffer.userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/select_buffers_for_network.sql b/src/core/SQL/PostgreSQL/14/select_buffers_for_network.sql
new file mode 100644 (file)
index 0000000..204a0c2
--- /dev/null
@@ -0,0 +1,4 @@
+SELECT bufferid
+FROM buffer
+WHERE networkid = :networkid and userid = :userid
+
diff --git a/src/core/SQL/PostgreSQL/14/select_checkidentity.sql b/src/core/SQL/PostgreSQL/14/select_checkidentity.sql
new file mode 100644 (file)
index 0000000..8254f03
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT count(*)
+FROM identity
+WHERE identityid = :identityid AND userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/select_connected_networks.sql b/src/core/SQL/PostgreSQL/14/select_connected_networks.sql
new file mode 100644 (file)
index 0000000..471f6c8
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT networkid
+FROM network
+WHERE userid = :userid AND connected = true
diff --git a/src/core/SQL/PostgreSQL/14/select_identities.sql b/src/core/SQL/PostgreSQL/14/select_identities.sql
new file mode 100644 (file)
index 0000000..cb7a883
--- /dev/null
@@ -0,0 +1,6 @@
+SELECT identityid, identityname, realname, awaynick, awaynickenabled,
+       awayreason, awayreasonenabled, autoawayenabled, autoawaytime, autoawayreason, autoawayreasonenabled,
+       detachawayenabled, detachawayreason, detachawayreasonenabled, ident, kickreason, partreason, quitreason,
+       sslcert, sslkey
+FROM identity
+WHERE userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/select_internaluser.sql b/src/core/SQL/PostgreSQL/14/select_internaluser.sql
new file mode 100644 (file)
index 0000000..8486d18
--- /dev/null
@@ -0,0 +1,2 @@
+SELECT min(userid)
+FROM quasseluser
diff --git a/src/core/SQL/PostgreSQL/14/select_messages.sql b/src/core/SQL/PostgreSQL/14/select_messages.sql
new file mode 100644 (file)
index 0000000..641179f
--- /dev/null
@@ -0,0 +1,8 @@
+SELECT messageid, time,  type, flags, sender, message
+FROM backlog
+JOIN sender ON backlog.senderid = sender.senderid
+WHERE bufferid = :bufferid
+    AND backlog.messageid >= :firstmsg
+    AND backlog.messageid < :lastmsg
+ORDER BY messageid DESC
+LIMIT :limit
diff --git a/src/core/SQL/PostgreSQL/14/select_messagesAll.sql b/src/core/SQL/PostgreSQL/14/select_messagesAll.sql
new file mode 100644 (file)
index 0000000..52285af
--- /dev/null
@@ -0,0 +1,8 @@
+SELECT messageid, bufferid, time,  type, flags, sender, message
+FROM backlog
+JOIN sender ON backlog.senderid = sender.senderid
+WHERE backlog.bufferid IN (SELECT bufferid FROM buffer WHERE userid = :userid)
+    AND backlog.messageid >= :firstmsg
+    AND backlog.messageid < :lastmsg
+ORDER BY messageid DESC
+LIMIT :limit
diff --git a/src/core/SQL/PostgreSQL/14/select_messagesAllNew.sql b/src/core/SQL/PostgreSQL/14/select_messagesAllNew.sql
new file mode 100644 (file)
index 0000000..a29f094
--- /dev/null
@@ -0,0 +1,7 @@
+SELECT messageid, bufferid, time,  type, flags, sender, message
+FROM backlog
+JOIN sender ON backlog.senderid = sender.senderid
+WHERE backlog.bufferid IN (SELECT bufferid FROM buffer WHERE userid = :userid)
+    AND backlog.messageid >= :firstmsg
+ORDER BY messageid DESC
+LIMIT :limit
diff --git a/src/core/SQL/PostgreSQL/14/select_messagesNewerThan.sql b/src/core/SQL/PostgreSQL/14/select_messagesNewerThan.sql
new file mode 100644 (file)
index 0000000..69d948d
--- /dev/null
@@ -0,0 +1,7 @@
+SELECT messageid, time,  type, flags, sender, message
+FROM backlog
+JOIN sender ON backlog.senderid = sender.senderid
+WHERE bufferid = :bufferid
+    AND backlog.messageid >= :firstmsg
+ORDER BY messageid DESC
+LIMIT :limit
diff --git a/src/core/SQL/PostgreSQL/14/select_messagesNewestK.sql b/src/core/SQL/PostgreSQL/14/select_messagesNewestK.sql
new file mode 100644 (file)
index 0000000..6cc81cc
--- /dev/null
@@ -0,0 +1,6 @@
+SELECT messageid, time,  type, flags, sender, message
+FROM backlog
+JOIN sender ON backlog.senderid = sender.senderid
+WHERE bufferid = :bufferid
+ORDER BY messageid DESC
+LIMIT :limit
diff --git a/src/core/SQL/PostgreSQL/14/select_networkExists.sql b/src/core/SQL/PostgreSQL/14/select_networkExists.sql
new file mode 100644 (file)
index 0000000..ce11c53
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT networkname
+FROM network
+WHERE userid = :userid AND networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/select_network_awaymsg.sql b/src/core/SQL/PostgreSQL/14/select_network_awaymsg.sql
new file mode 100644 (file)
index 0000000..8b55cf4
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT awaymessage
+FROM network
+WHERE userid = :userid AND networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/select_network_usermode.sql b/src/core/SQL/PostgreSQL/14/select_network_usermode.sql
new file mode 100644 (file)
index 0000000..a6d6a77
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT usermode
+FROM network
+WHERE userid = :userid AND networkid = :networkid
\ No newline at end of file
diff --git a/src/core/SQL/PostgreSQL/14/select_networks_for_user.sql b/src/core/SQL/PostgreSQL/14/select_networks_for_user.sql
new file mode 100644 (file)
index 0000000..08855c9
--- /dev/null
@@ -0,0 +1,5 @@
+SELECT networkid, networkname, identityid, servercodec, encodingcodec, decodingcodec,
+       userandomserver, perform, useautoidentify, autoidentifyservice, autoidentifypassword,
+       useautoreconnect, autoreconnectinterval, autoreconnectretries, unlimitedconnectretries, rejoinchannels
+FROM network
+WHERE userid = :userid
\ No newline at end of file
diff --git a/src/core/SQL/PostgreSQL/14/select_nicks.sql b/src/core/SQL/PostgreSQL/14/select_nicks.sql
new file mode 100644 (file)
index 0000000..41dc6e4
--- /dev/null
@@ -0,0 +1,4 @@
+SELECT nick
+FROM identity_nick
+WHERE identityid = :identityid
+ORDER BY nickid ASC
diff --git a/src/core/SQL/PostgreSQL/14/select_persistent_channels.sql b/src/core/SQL/PostgreSQL/14/select_persistent_channels.sql
new file mode 100644 (file)
index 0000000..8288a6a
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT buffername, key
+FROM buffer
+WHERE userid = :userid AND networkid = :networkid AND buffertype = 2 AND joined = true
diff --git a/src/core/SQL/PostgreSQL/14/select_servers_for_network.sql b/src/core/SQL/PostgreSQL/14/select_servers_for_network.sql
new file mode 100644 (file)
index 0000000..d6b5cf4
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT hostname, port, password, ssl, sslversion, useproxy, proxytype, proxyhost, proxyport, proxyuser, proxypass
+FROM ircserver
+WHERE networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/select_user_setting.sql b/src/core/SQL/PostgreSQL/14/select_user_setting.sql
new file mode 100644 (file)
index 0000000..a5da306
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT settingvalue
+FROM user_setting
+WHERE userid = :userid AND settingname = :settingname
diff --git a/src/core/SQL/PostgreSQL/14/select_userid.sql b/src/core/SQL/PostgreSQL/14/select_userid.sql
new file mode 100644 (file)
index 0000000..181c1b3
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT userid
+FROM quasseluser
+WHERE username = :username
diff --git a/src/core/SQL/PostgreSQL/14/setup_000_quasseluser.sql b/src/core/SQL/PostgreSQL/14/setup_000_quasseluser.sql
new file mode 100644 (file)
index 0000000..cd8292c
--- /dev/null
@@ -0,0 +1,5 @@
+CREATE TABLE quasseluser (
+       userid serial NOT NULL PRIMARY KEY,
+       username varchar(64) UNIQUE NOT NULL,
+       password char(40) NOT NULL -- hex reppresentation of sha1 hashes
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_010_sender.sql b/src/core/SQL/PostgreSQL/14/setup_010_sender.sql
new file mode 100644 (file)
index 0000000..0e9cdf1
--- /dev/null
@@ -0,0 +1,4 @@
+CREATE TABLE sender ( -- THE SENDER OF IRC MESSAGES
+       senderid serial NOT NULL PRIMARY KEY,
+       sender varchar(128) UNIQUE NOT NULL
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_020_identity.sql b/src/core/SQL/PostgreSQL/14/setup_020_identity.sql
new file mode 100644 (file)
index 0000000..35ffe72
--- /dev/null
@@ -0,0 +1,24 @@
+CREATE TABLE identity (
+       identityid serial PRIMARY KEY,
+       userid integer NOT NULL REFERENCES quasseluser (userid) ON DELETE CASCADE,
+       identityname varchar(64) NOT NULL,
+       realname varchar(128) NOT NULL,
+       awaynick varchar(64),
+       awaynickenabled boolean NOT NULL DEFAULT FALSE,
+       awayreason varchar(256),
+       awayreasonenabled boolean NOT NULL DEFAULT FALSE,
+       autoawayenabled boolean NOT NULL DEFAULT FALSE,
+       autoawaytime integer NOT NULL,
+       autoawayreason varchar(256),
+       autoawayreasonenabled boolean NOT NULL DEFAULT FALSE,
+       detachawayenabled boolean NOT NULL DEFAULT FALSE,
+       detachawayreason varchar(256),
+       detachawayreasonenabled boolean NOT NULL DEFAULT FALSE,
+       ident varchar(64),
+       kickreason varchar(256),
+       partreason varchar(256),
+       quitreason varchar(256),
+       sslcert bytea,
+       sslkey bytea,
+       UNIQUE (userid, identityname)
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_030_identity_nick.sql b/src/core/SQL/PostgreSQL/14/setup_030_identity_nick.sql
new file mode 100644 (file)
index 0000000..65fb5ec
--- /dev/null
@@ -0,0 +1,6 @@
+CREATE TABLE identity_nick (
+       nickid serial PRIMARY KEY,
+       identityid integer NOT NULL REFERENCES identity (identityid) ON DELETE CASCADE,
+       nick varchar(64) NOT NULL,
+       UNIQUE (identityid, nick)
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_040_network.sql b/src/core/SQL/PostgreSQL/14/setup_040_network.sql
new file mode 100644 (file)
index 0000000..87f48b4
--- /dev/null
@@ -0,0 +1,25 @@
+CREATE TABLE network (
+       networkid serial NOT NULL PRIMARY KEY,
+       userid integer NOT NULL REFERENCES quasseluser (userid) ON DELETE CASCADE,
+       networkname varchar(32) NOT NULL,
+       identityid integer REFERENCES identity (identityid) ON DELETE SET NULL,
+       encodingcodec varchar(32) NOT NULL DEFAULT 'ISO-8859-15',
+       decodingcodec varchar(32) NOT NULL DEFAULT 'ISO-8859-15',
+       servercodec varchar(32),
+       userandomserver boolean NOT NULL DEFAULT FALSE,
+       perform TEXT,
+       useautoidentify boolean NOT NULL DEFAULT FALSE,
+       autoidentifyservice varchar(128),
+       autoidentifypassword varchar(128),
+       useautoreconnect boolean NOT NULL DEFAULT TRUE,
+       autoreconnectinterval integer NOT NULL DEFAULT 0,
+       autoreconnectretries integer NOT NULL DEFAULT 0,
+       unlimitedconnectretries boolean NOT NULL DEFAULT FALSE,
+       rejoinchannels boolean NOT NULL DEFAULT FALSE,
+       connected boolean NOT NULL DEFAULT FALSE,
+       usermode varchar(32), -- user mode to restore
+       awaymessage varchar(256), -- away message to restore (empty if not away)
+       attachperform text, -- perform list for on attach
+       detachperform text, -- perform list for on detach
+       UNIQUE (userid, networkname)
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_050_buffer.sql b/src/core/SQL/PostgreSQL/14/setup_050_buffer.sql
new file mode 100644 (file)
index 0000000..d620a76
--- /dev/null
@@ -0,0 +1,13 @@
+create TABLE buffer (
+       bufferid serial PRIMARY KEY,
+       userid integer NOT NULL REFERENCES quasseluser (userid) ON DELETE CASCADE,
+       groupid integer,
+       networkid integer NOT NULL REFERENCES network (networkid) ON DELETE CASCADE,
+       buffername varchar(128) NOT NULL,
+       buffercname varchar(128) NOT NULL, -- CANONICAL BUFFER NAME (lowercase version)
+       buffertype integer NOT NULL DEFAULT 0,
+       lastseenmsgid integer NOT NULL DEFAULT 0,
+       key varchar(128),
+       joined boolean NOT NULL DEFAULT FALSE, -- BOOL
+       UNIQUE(userid, networkid, buffercname)
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_060_backlog.sql b/src/core/SQL/PostgreSQL/14/setup_060_backlog.sql
new file mode 100644 (file)
index 0000000..1f281b0
--- /dev/null
@@ -0,0 +1,9 @@
+CREATE TABLE backlog (
+       messageid serial PRIMARY KEY,
+       time integer NOT NULL,
+       bufferid integer NOT NULL REFERENCES buffer (bufferid) ON DELETE CASCADE,
+       type integer NOT NULL,
+       flags integer NOT NULL,
+       senderid integer NOT NULL REFERENCES sender (senderid) ON DELETE SET NULL,
+       message TEXT
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_070_coreinfo.sql b/src/core/SQL/PostgreSQL/14/setup_070_coreinfo.sql
new file mode 100644 (file)
index 0000000..652ec69
--- /dev/null
@@ -0,0 +1,4 @@
+CREATE TABLE coreinfo (
+       key TEXT NOT NULL PRIMARY KEY,
+       value TEXT
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_080_ircservers.sql b/src/core/SQL/PostgreSQL/14/setup_080_ircservers.sql
new file mode 100644 (file)
index 0000000..c778440
--- /dev/null
@@ -0,0 +1,16 @@
+CREATE TABLE ircserver (
+    serverid serial PRIMARY KEY,
+    userid integer NOT NULL REFERENCES quasseluser (userid) ON DELETE CASCADE,
+    networkid integer NOT NULL REFERENCES network (networkid) ON DELETE CASCADE,
+    hostname varchar(128) NOT NULL,
+    port integer NOT NULL DEFAULT 6667,
+    password varchar(64),
+    ssl boolean NOT NULL DEFAULT FALSE, -- bool
+    sslversion integer NOT NULL DEFAULT 0,
+    useproxy boolean NOT NULL DEFAULT FALSE, -- bool
+    proxytype integer NOT NULL DEFAULT 0,
+    proxyhost varchar(128) NOT NULL DEFAULT 'localhost',
+    proxyport integer NOT NULL DEFAULT 8080,
+    proxyuser varchar(64),
+    proxypass varchar(64)
+)
diff --git a/src/core/SQL/PostgreSQL/14/setup_090_backlog_idx.sql b/src/core/SQL/PostgreSQL/14/setup_090_backlog_idx.sql
new file mode 100644 (file)
index 0000000..25b5711
--- /dev/null
@@ -0,0 +1 @@
+CREATE INDEX backlog_bufferid_idx ON backlog(bufferid, messageid DESC)
diff --git a/src/core/SQL/PostgreSQL/14/setup_100_user_setting.sql b/src/core/SQL/PostgreSQL/14/setup_100_user_setting.sql
new file mode 100644 (file)
index 0000000..bf6d85d
--- /dev/null
@@ -0,0 +1,6 @@
+CREATE TABLE user_setting (
+    userid integer NOT NULL REFERENCES quasseluser (userid) ON DELETE CASCADE,
+    settingname TEXT NOT NULL,
+    settingvalue bytea,
+    PRIMARY KEY (userid, settingname)
+)
diff --git a/src/core/SQL/PostgreSQL/14/update_backlog_bufferid.sql b/src/core/SQL/PostgreSQL/14/update_backlog_bufferid.sql
new file mode 100644 (file)
index 0000000..b490b29
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE backlog
+SET bufferid = :newbufferid
+WHERE bufferid = :oldbufferid
diff --git a/src/core/SQL/PostgreSQL/14/update_buffer_lastseen.sql b/src/core/SQL/PostgreSQL/14/update_buffer_lastseen.sql
new file mode 100644 (file)
index 0000000..5541505
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE buffer
+SET lastseenmsgid = :lastseenmsgid
+WHERE userid = :userid AND bufferid = :bufferid
diff --git a/src/core/SQL/PostgreSQL/14/update_buffer_name.sql b/src/core/SQL/PostgreSQL/14/update_buffer_name.sql
new file mode 100644 (file)
index 0000000..14d65e7
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE buffer
+SET buffername = :buffername, buffercname = :buffercname
+WHERE bufferid = :bufferid
diff --git a/src/core/SQL/PostgreSQL/14/update_buffer_persistent_channel.sql b/src/core/SQL/PostgreSQL/14/update_buffer_persistent_channel.sql
new file mode 100644 (file)
index 0000000..e75360a
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE buffer
+SET joined = :joined
+WHERE userid = :userid AND networkid = :networkid AND buffercname = :buffercname AND buffertype = 2
diff --git a/src/core/SQL/PostgreSQL/14/update_buffer_set_channel_key.sql b/src/core/SQL/PostgreSQL/14/update_buffer_set_channel_key.sql
new file mode 100644 (file)
index 0000000..803d6fd
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE buffer
+SET key = :key
+WHERE userid = :userid AND networkid = :networkid AND buffercname = :buffercname AND buffertype = 2
diff --git a/src/core/SQL/PostgreSQL/14/update_identity.sql b/src/core/SQL/PostgreSQL/14/update_identity.sql
new file mode 100644 (file)
index 0000000..c25a708
--- /dev/null
@@ -0,0 +1,21 @@
+UPDATE identity
+SET    identityname = :identityname,
+       realname = :realname,
+       awaynick = :awaynick,
+       awaynickenabled = :awaynickenabled,
+       awayreason = :awayreason,
+       awayreasonenabled = :awayreasonenabled,
+       autoawayenabled = :autoawayenabled,
+       autoawaytime = :autoawaytime,
+       autoawayreason = :autoawayreason,
+       autoawayreasonenabled = :autoawayreasonenabled,
+       detachawayenabled = :detachawayenabled,
+       detachawayreason = :detachawayreason,
+       detachawayreasonenabled = :detachawayreasonenabled,
+       ident = :ident,
+       kickreason = :kickreason,
+       partreason = :partreason,
+       quitreason = :quitreason,
+       sslcert = :sslcert,
+       sslkey = :sslkey
+WHERE  identityid = :identityid
diff --git a/src/core/SQL/PostgreSQL/14/update_network.sql b/src/core/SQL/PostgreSQL/14/update_network.sql
new file mode 100644 (file)
index 0000000..8d5a462
--- /dev/null
@@ -0,0 +1,17 @@
+UPDATE network SET
+networkname = :networkname,
+identityid = :identityid,
+servercodec = :servercodec,
+encodingcodec = :encodingcodec,
+decodingcodec = :decodingcodec,
+userandomserver = :userandomserver,
+perform = :perform,
+useautoidentify = :useautoidentify,
+autoidentifyservice = :autoidentifyservice,
+autoidentifypassword = :autoidentifypassword,
+useautoreconnect = :useautoreconnect,
+autoreconnectinterval = :autoreconnectinterval,
+autoreconnectretries = :autoreconnectretries,
+unlimitedconnectretries = :unlimitedconnectretries,
+rejoinchannels = :rejoinchannels
+WHERE networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/update_network_connected.sql b/src/core/SQL/PostgreSQL/14/update_network_connected.sql
new file mode 100644 (file)
index 0000000..0bd89de
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE network
+SET connected = :connected
+WHERE userid = :userid AND networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/update_network_set_awaymsg.sql b/src/core/SQL/PostgreSQL/14/update_network_set_awaymsg.sql
new file mode 100644 (file)
index 0000000..e0254da
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE network
+SET awaymessage = :awaymsg
+WHERE userid = :userid AND networkid = :networkid
diff --git a/src/core/SQL/PostgreSQL/14/update_network_set_usermode.sql b/src/core/SQL/PostgreSQL/14/update_network_set_usermode.sql
new file mode 100644 (file)
index 0000000..b87c4c8
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE network
+SET usermode = :usermode
+WHERE userid = :userid AND networkid = :networkid
\ No newline at end of file
diff --git a/src/core/SQL/PostgreSQL/14/update_user_setting.sql b/src/core/SQL/PostgreSQL/14/update_user_setting.sql
new file mode 100644 (file)
index 0000000..3585fbc
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE user_setting
+SET settingvalue = :settingvalue
+WHERE userid = :userid AND settingname = :settingname
diff --git a/src/core/SQL/PostgreSQL/14/update_username.sql b/src/core/SQL/PostgreSQL/14/update_username.sql
new file mode 100644 (file)
index 0000000..951e17a
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE quasseluser
+SET username = :username
+WHERE userid = :userid
diff --git a/src/core/SQL/PostgreSQL/14/update_userpassword.sql b/src/core/SQL/PostgreSQL/14/update_userpassword.sql
new file mode 100644 (file)
index 0000000..44a514a
--- /dev/null
@@ -0,0 +1,3 @@
+UPDATE quasseluser
+SET password = :password
+WHERE userid = :userid
index 7e5dee5..fa230f3 100644 (file)
@@ -72,6 +72,9 @@ void AbstractSqlStorage::addConnectionToPool() {
   if(!hostName().isEmpty())
     db.setHostName(hostName());
 
   if(!hostName().isEmpty())
     db.setHostName(hostName());
 
+  if(port() != -1)
+    db.setPort(port());
+
   if(!userName().isEmpty()) {
     db.setUserName(userName());
     db.setPassword(password());
   if(!userName().isEmpty()) {
     db.setUserName(userName());
     db.setPassword(password());
@@ -84,7 +87,7 @@ void AbstractSqlStorage::addConnectionToPool() {
 }
 
 Storage::State AbstractSqlStorage::init(const QVariantMap &settings) {
 }
 
 Storage::State AbstractSqlStorage::init(const QVariantMap &settings) {
-  Q_UNUSED(settings)
+  setConnectionProperties(settings);
 
   QSqlDatabase db = logDb();
   if(!db.isValid() || !db.isOpen())
 
   QSqlDatabase db = logDb();
   if(!db.isValid() || !db.isOpen())
@@ -108,7 +111,7 @@ Storage::State AbstractSqlStorage::init(const QVariantMap &settings) {
     }
   }
 
     }
   }
 
-  quInfo() << "Storage Backend is ready. Quassel Schema Version:" << installedSchemaVersion();
+  quInfo() << qPrintable(displayName()) << "Storage Backend is ready. Quassel Schema Version:" << installedSchemaVersion();
   return IsReady;
 }
 
   return IsReady;
 }
 
@@ -141,21 +144,28 @@ QStringList AbstractSqlStorage::setupQueries() {
 }
 
 bool AbstractSqlStorage::setup(const QVariantMap &settings) {
 }
 
 bool AbstractSqlStorage::setup(const QVariantMap &settings) {
-  Q_UNUSED(settings)
+  setConnectionProperties(settings);
   QSqlDatabase db = logDb();
   if(!db.isOpen()) {
     qCritical() << "Unable to setup Logging Backend!";
     return false;
   }
 
   QSqlDatabase db = logDb();
   if(!db.isOpen()) {
     qCritical() << "Unable to setup Logging Backend!";
     return false;
   }
 
+  db.transaction();
   foreach(QString queryString, setupQueries()) {
     QSqlQuery query = db.exec(queryString);
     if(!watchQuery(query)) {
       qCritical() << "Unable to setup Logging Backend!";
   foreach(QString queryString, setupQueries()) {
     QSqlQuery query = db.exec(queryString);
     if(!watchQuery(query)) {
       qCritical() << "Unable to setup Logging Backend!";
+      db.rollback();
       return false;
     }
   }
       return false;
     }
   }
-  return setupSchemaVersion(schemaVersion());
+  bool success = setupSchemaVersion(schemaVersion());
+  if(success)
+    db.commit();
+  else
+    db.rollback();
+  return success;
 }
 
 QStringList AbstractSqlStorage::upgradeQueries(int version) {
 }
 
 QStringList AbstractSqlStorage::upgradeQueries(int version) {
index e3b4ec4..e087c6d 100644 (file)
@@ -56,8 +56,10 @@ protected:
   virtual bool updateSchemaVersion(int newVersion) = 0;
   virtual bool setupSchemaVersion(int version) = 0;
 
   virtual bool updateSchemaVersion(int newVersion) = 0;
   virtual bool setupSchemaVersion(int version) = 0;
 
+  virtual void setConnectionProperties(const QVariantMap &properties) = 0;
   virtual QString driverName() = 0;
   inline virtual QString hostName() { return QString(); }
   virtual QString driverName() = 0;
   inline virtual QString hostName() { return QString(); }
+  inline virtual int port() { return -1; }
   virtual QString databaseName() = 0;
   inline virtual QString userName() { return QString(); }
   inline virtual QString password() { return QString(); }
   virtual QString databaseName() = 0;
   inline virtual QString userName() { return QString(); }
   inline virtual QString password() { return QString(); }
index e1a5360..c782793 100644 (file)
@@ -23,6 +23,7 @@
 #include "core.h"
 #include "coresession.h"
 #include "coresettings.h"
 #include "core.h"
 #include "coresession.h"
 #include "coresettings.h"
+#include "postgresqlstorage.h"
 #include "quassel.h"
 #include "signalproxy.h"
 #include "sqlitestorage.h"
 #include "quassel.h"
 #include "signalproxy.h"
 #include "sqlitestorage.h"
@@ -132,6 +133,7 @@ Core::Core()
 
   // Register storage backends here!
   registerStorageBackend(new SqliteStorage(this));
 
   // Register storage backends here!
   registerStorageBackend(new SqliteStorage(this));
+  registerStorageBackend(new PostgreSqlStorage(this));
 
   connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage()));
   _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes
 
   connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage()));
   _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes
@@ -273,12 +275,14 @@ bool Core::initStorage(QVariantMap dbSettings, bool setup) {
     return false;
   }
 
     return false;
   }
 
-  Storage::State storageState = storage->init(dbSettings);
+  QVariantMap connectionProperties = dbSettings["ConnectionProperties"].toMap();
+
+  Storage::State storageState = storage->init(connectionProperties);
   switch(storageState) {
   case Storage::NeedsSetup:
     if(!setup)
       return false; // trigger setup process
   switch(storageState) {
   case Storage::NeedsSetup:
     if(!setup)
       return false; // trigger setup process
-    if(storage->setup(dbSettings))
+    if(storage->setup(connectionProperties))
       return initStorage(dbSettings, false);
     // if setup wasn't successfull we mark the backend as unavailable
   case Storage::NotAvailable:
       return initStorage(dbSettings, false);
     // if setup wasn't successfull we mark the backend as unavailable
   case Storage::NotAvailable:
@@ -501,6 +505,8 @@ void Core::processClientMessage(QTcpSocket *socket, const QVariantMap &msg) {
         QVariantMap v;
         v["DisplayName"] = backend->displayName();
         v["Description"] = backend->description();
         QVariantMap v;
         v["DisplayName"] = backend->displayName();
         v["Description"] = backend->description();
+       v["ConnectionProperties"] = backend->setupKeys();
+       qDebug() << backend->setupKeys();
         backends.append(v);
       }
       reply["StorageBackends"] = backends;
         backends.append(v);
       }
       reply["StorageBackends"] = backends;
index 2c1fa07..6d743e8 100644 (file)
@@ -134,17 +134,6 @@ class Core : public QObject {
     return instance()->_storage->networks(user);
   }
 
     return instance()->_storage->networks(user);
   }
 
-  //! Get the NetworkId for a network name.
-  /** \note This method is threadsafe.
-   *
-   *  \param user    The core user
-   *  \param network The name of the network
-   *  \return The NetworkId corresponding to the given network.
-   */
-  static inline NetworkId networkId(UserId user, const QString &network) {
-    return instance()->_storage->getNetworkId(user, network);
-  }
-
   //! Get a list of Networks to restore
   /** Return a list of networks the user was connected at the time of core shutdown
    *  \note This method is threadsafe.
   //! Get a list of Networks to restore
   /** Return a list of networks the user was connected at the time of core shutdown
    *  \note This method is threadsafe.
index f0c84f3..3056b8a 100644 (file)
@@ -73,7 +73,7 @@ CoreApplication::~CoreApplication() {
 
 bool CoreApplication::init() {
   if(Quassel::init() && _internal->init()) {
 
 bool CoreApplication::init() {
   if(Quassel::init() && _internal->init()) {
-    qInstallMsgHandler(Logger::logMessage);
+    // qInstallMsgHandler(Logger::logMessage);
     return true;
   }
   return false;
     return true;
   }
   return false;
index a357044..ece012e 100644 (file)
@@ -333,7 +333,14 @@ void CoreNetwork::socketInitialized() {
   if(!server.password.isEmpty()) {
     putRawLine(serverEncode(QString("PASS %1").arg(server.password)));
   }
   if(!server.password.isEmpty()) {
     putRawLine(serverEncode(QString("PASS %1").arg(server.password)));
   }
-  putRawLine(serverEncode(QString("NICK :%1").arg(identity->nicks()[0])));
+  QString nick;
+  if(identity->nicks().isEmpty()) {
+    nick = "quassel";
+    qWarning() << "CoreNetwork::socketInitialized(): no nicks supplied for identity Id" << identity->id();
+  } else {
+    nick = identity->nicks()[0];
+  }
+  putRawLine(serverEncode(QString("NICK :%1").arg(nick)));
   putRawLine(serverEncode(QString("USER %1 8 * :%2").arg(identity->ident(), identity->realName())));
 }
 
   putRawLine(serverEncode(QString("USER %1 8 * :%2").arg(identity->ident(), identity->realName())));
 }
 
index b5ae06c..7a4f622 100644 (file)
@@ -272,6 +272,7 @@ void CoreSession::createIdentity(const Identity &identity, const QVariantMap &ad
   if(additional.contains("CertPem"))
     coreIdentity.setSslCert(additional["CertPem"].toByteArray());
 #endif
   if(additional.contains("CertPem"))
     coreIdentity.setSslCert(additional["CertPem"].toByteArray());
 #endif
+  qDebug() << Q_FUNC_INFO;
   IdentityId id = Core::createIdentity(user(), coreIdentity);
   if(!id.isValid())
     return;
   IdentityId id = Core::createIdentity(user(), coreIdentity);
   if(!id.isValid())
     return;
diff --git a/src/core/postgresqlstorage.cpp b/src/core/postgresqlstorage.cpp
new file mode 100644 (file)
index 0000000..56be64e
--- /dev/null
@@ -0,0 +1,1235 @@
+/***************************************************************************
+ *   Copyright (C) 2005-07 by the Quassel Project                          *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program 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 General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "postgresqlstorage.h"
+
+#include <QtSql>
+
+#include "logger.h"
+#include "network.h"
+#include "quassel.h"
+
+int PostgreSqlStorage::_maxRetryCount = 150; // yes this is a large number... only other way to "handle" this is bailing out...
+
+PostgreSqlStorage::PostgreSqlStorage(QObject *parent)
+  : AbstractSqlStorage(parent),
+    _port(-1)
+{
+}
+
+PostgreSqlStorage::~PostgreSqlStorage() {
+}
+
+bool PostgreSqlStorage::isAvailable() const {
+  if(!QSqlDatabase::isDriverAvailable("QPSQL")) return false;
+  return true;
+}
+
+QString PostgreSqlStorage::displayName() const {
+  return QString("PostgreSQL");
+}
+
+QString PostgreSqlStorage::description() const {
+  // FIXME: proper description
+  return tr("PostgreSQL Turbo Bomber HD!");
+}
+
+QVariantMap PostgreSqlStorage::setupKeys() const {
+  QVariantMap map;
+  map["Username"] = QVariant(QString("quassel"));
+  map["Password"] = QVariant(QString());
+  map["Hostname"] = QVariant(QString("localhost"));
+  map["Port"] = QVariant(5432);
+  map["Database"] = QVariant(QString("quassel"));
+  return map;
+}
+
+void PostgreSqlStorage::setConnectionProperties(const QVariantMap &properties) {
+  _userName = properties["Username"].toString();
+  _password = properties["Password"].toString();
+  _hostName = properties["Hostname"].toString();
+  _port = properties["Port"].toInt();
+  _databaseName = properties["Database"].toString();
+}
+
+int PostgreSqlStorage::installedSchemaVersion() {
+  QSqlQuery query = logDb().exec("SELECT value FROM coreinfo WHERE key = 'schemaversion'");
+  if(query.first())
+    return query.value(0).toInt();
+
+  // maybe it's really old... (schema version 0)
+  query = logDb().exec("SELECT MAX(version) FROM coreinfo");
+  if(query.first())
+    return query.value(0).toInt();
+
+  return AbstractSqlStorage::installedSchemaVersion();
+}
+
+bool PostgreSqlStorage::updateSchemaVersion(int newVersion) {
+  QSqlQuery query(logDb());
+  query.prepare("UPDATE coreinfo SET value = :version WHERE key = 'schemaversion'");
+  query.bindValue(":version", newVersion);
+  query.exec();
+
+  bool success = true;
+  if(query.lastError().isValid()) {
+    qCritical() << "PostgreSqlStorage::updateSchemaVersion(int): Updating schema version failed!";
+    success = false;
+  }
+  return success;
+}
+
+bool PostgreSqlStorage::setupSchemaVersion(int version) {
+  QSqlQuery query(logDb());
+  query.prepare("INSERT INTO coreinfo (key, value) VALUES ('schemaversion', :version)");
+  query.bindValue(":version", version);
+  query.exec();
+
+  bool success = true;
+  if(query.lastError().isValid()) {
+    qCritical() << "PostgreSqlStorage::setupSchemaVersion(int): Updating schema version failed!";
+    success = false;
+  }
+  return success;
+}
+
+UserId PostgreSqlStorage::addUser(const QString &user, const QString &password) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("insert_quasseluser"));
+  query.bindValue(":username", user);
+  query.bindValue(":password", cryptedPassword(password));
+  safeExec(query);
+  if(!watchQuery(query))
+    return 0;
+
+  query.first();
+  UserId uid = query.value(0).toInt();
+  emit userAdded(uid, user);
+  return uid;
+}
+
+void PostgreSqlStorage::updateUser(UserId user, const QString &password) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_userpassword"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":password", cryptedPassword(password));
+  safeExec(query);
+}
+
+void PostgreSqlStorage::renameUser(UserId user, const QString &newName) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_username"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":username", newName);
+  safeExec(query);
+  emit userRenamed(user, newName);
+}
+
+UserId PostgreSqlStorage::validateUser(const QString &user, const QString &password) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_authuser"));
+  query.bindValue(":username", user);
+  query.bindValue(":password", cryptedPassword(password));
+  safeExec(query);
+
+  if(query.first()) {
+    return query.value(0).toInt();
+  } else {
+    return 0;
+  }
+}
+
+UserId PostgreSqlStorage::internalUser() {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_internaluser"));
+  safeExec(query);
+
+  if(query.first()) {
+    return query.value(0).toInt();
+  } else {
+    return 0;
+  }
+}
+
+void PostgreSqlStorage::delUser(UserId user) {
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::delUser(): cannot start transaction!";
+    return;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("delete_quasseluser"));
+  query.bindValue(":userid", user.toInt());
+  safeExec(query);
+  if(!watchQuery(query)) {
+    db.rollback();
+    return;
+  } else {
+    db.commit();
+    emit userRemoved(user);
+  }
+}
+
+void PostgreSqlStorage::setUserSetting(UserId userId, const QString &settingName, const QVariant &data) {
+  QByteArray rawData;
+  QDataStream out(&rawData, QIODevice::WriteOnly);
+  out.setVersion(QDataStream::Qt_4_2);
+  out << data;
+
+  QSqlDatabase db = logDb();  
+  QSqlQuery query(db);
+  query.prepare(queryString("insert_user_setting"));
+  query.bindValue(":userid", userId.toInt());
+  query.bindValue(":settingname", settingName);
+  query.bindValue(":settingvalue", rawData);
+  safeExec(query);
+
+  if(query.lastError().isValid()) {
+    QSqlQuery updateQuery(db);
+    updateQuery.prepare(queryString("update_user_setting"));
+    updateQuery.bindValue(":userid", userId.toInt());
+    updateQuery.bindValue(":settingname", settingName);
+    updateQuery.bindValue(":settingvalue", rawData);
+    safeExec(updateQuery);
+  }
+
+}
+
+QVariant PostgreSqlStorage::getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_user_setting"));
+  query.bindValue(":userid", userId.toInt());
+  query.bindValue(":settingname", settingName);
+  safeExec(query);
+
+  if(query.first()) {
+    QVariant data;
+    QByteArray rawData = query.value(0).toByteArray();
+    QDataStream in(&rawData, QIODevice::ReadOnly);
+    in.setVersion(QDataStream::Qt_4_2);
+    in >> data;
+    return data;
+  } else {
+    return defaultData;
+  }
+}
+
+IdentityId PostgreSqlStorage::createIdentity(UserId user, CoreIdentity &identity) {
+  IdentityId identityId;
+
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::createIdentity(): Unable to start Transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return identityId;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("insert_identity"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":identityname", identity.identityName());
+  query.bindValue(":realname", identity.realName());
+  query.bindValue(":awaynick", identity.awayNick());
+  query.bindValue(":awaynickenabled", identity.awayNickEnabled());
+  query.bindValue(":awayreason", identity.awayReason());
+  query.bindValue(":awayreasonenabled", identity.awayReasonEnabled());
+  query.bindValue(":autoawayenabled", identity.awayReasonEnabled());
+  query.bindValue(":autoawaytime", identity.autoAwayTime());
+  query.bindValue(":autoawayreason", identity.autoAwayReason());
+  query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled());
+  query.bindValue(":detachawayenabled", identity.detachAwayEnabled());
+  query.bindValue(":detachawayreason", identity.detachAwayReason());
+  query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled());
+  query.bindValue(":ident", identity.ident());
+  query.bindValue(":kickreason", identity.kickReason());
+  query.bindValue(":partreason", identity.partReason());
+  query.bindValue(":quitreason", identity.quitReason());
+#ifdef HAVE_SSL
+  query.bindValue(":sslcert", identity.sslCert().toPem());
+  query.bindValue(":sslkey", identity.sslKey().toPem());
+#else
+  query.bindValue(":sslcert", QByteArray());
+  query.bindValue(":sslkey", QByteArray());
+#endif
+  safeExec(query);
+  if(query.lastError().isValid()) {
+    watchQuery(query);
+    db.rollback();
+    return IdentityId();
+  }
+
+  qDebug() << "creatId" << query.first() << query.value(0).toInt();
+  identityId = query.value(0).toInt();
+  identity.setId(identityId);
+
+  if(!identityId.isValid()) {
+    watchQuery(query);
+    db.rollback();
+    return IdentityId();
+  }
+
+  QSqlQuery insertNickQuery(db);
+  insertNickQuery.prepare(queryString("insert_nick"));
+  foreach(QString nick, identity.nicks()) {
+    insertNickQuery.bindValue(":identityid", identityId.toInt());
+    insertNickQuery.bindValue(":nick", nick);
+    safeExec(insertNickQuery);
+    if(!watchQuery(insertNickQuery)) {
+      db.rollback();
+      return IdentityId();
+    }
+  }
+
+  if(!db.commit()) {
+    qWarning() << "PostgreSqlStorage::createIdentity(): commiting data failed!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return IdentityId();
+  }
+  return identityId;
+}
+
+bool PostgreSqlStorage::updateIdentity(UserId user, const CoreIdentity &identity) {
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::updateIdentity(): Unable to start Transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return false;
+  }
+  
+  QSqlQuery checkQuery(db);
+  checkQuery.prepare(queryString("select_checkidentity"));
+  checkQuery.bindValue(":identityid", identity.id().toInt());
+  checkQuery.bindValue(":userid", user.toInt());
+  safeExec(checkQuery);
+
+  // there should be exactly one identity for the given id and user
+  if(!checkQuery.first() || checkQuery.value(0).toInt() != 1) {
+    db.rollback();
+    return false;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("update_identity"));
+  query.bindValue(":identityname", identity.identityName());
+  query.bindValue(":realname", identity.realName());
+  query.bindValue(":awaynick", identity.awayNick());
+  query.bindValue(":awaynickenabled", identity.awayNickEnabled());
+  query.bindValue(":awayreason", identity.awayReason());
+  query.bindValue(":awayreasonenabled", identity.awayReasonEnabled());
+  query.bindValue(":autoawayenabled", identity.awayReasonEnabled());
+  query.bindValue(":autoawaytime", identity.autoAwayTime());
+  query.bindValue(":autoawayreason", identity.autoAwayReason());
+  query.bindValue(":autoawayreasonenabled", identity.autoAwayReasonEnabled());
+  query.bindValue(":detachawayenabled", identity.detachAwayEnabled());
+  query.bindValue(":detachawayreason", identity.detachAwayReason());
+  query.bindValue(":detachawayreasonenabled", identity.detachAwayReasonEnabled());
+  query.bindValue(":ident", identity.ident());
+  query.bindValue(":kickreason", identity.kickReason());
+  query.bindValue(":partreason", identity.partReason());
+  query.bindValue(":quitreason", identity.quitReason());
+#ifdef HAVE_SSL
+  query.bindValue(":sslcert", identity.sslCert().toPem());
+  query.bindValue(":sslkey", identity.sslKey().toPem());
+#else
+  query.bindValue(":sslcert", QByteArray());
+  query.bindValue(":sslkey", QByteArray());
+#endif
+  query.bindValue(":identityid", identity.id().toInt());
+
+  safeExec(query);
+  if(!watchQuery(query)) {
+    db.rollback();
+    return false;
+  }
+  
+  QSqlQuery deleteNickQuery(db);
+  deleteNickQuery.prepare(queryString("delete_nicks"));
+  deleteNickQuery.bindValue(":identityid", identity.id().toInt());
+  safeExec(deleteNickQuery);
+  if(!watchQuery(deleteNickQuery)) {
+    db.rollback();
+    return false;
+  }
+
+  QSqlQuery insertNickQuery(db);
+  insertNickQuery.prepare(queryString("insert_nick"));
+  foreach(QString nick, identity.nicks()) {
+    insertNickQuery.bindValue(":identityid", identity.id().toInt());
+    insertNickQuery.bindValue(":nick", nick);
+    safeExec(insertNickQuery);
+    if(!watchQuery(insertNickQuery)) {
+      db.rollback();
+      return false;
+    }
+  }
+
+  if(!db.commit()) {
+    qWarning() << "PostgreSqlStorage::updateIdentity(): commiting data failed!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return false;
+  }
+  return true;
+}
+
+void PostgreSqlStorage::removeIdentity(UserId user, IdentityId identityId) {
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::removeIdentity(): Unable to start Transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("delete_identity"));
+  query.bindValue(":identityid", identityId.toInt());
+  query.bindValue(":userid", user.toInt());
+  safeExec(query);
+  if(!watchQuery(query)) {
+    db.rollback();
+  } else {
+    db.commit();
+  }
+}
+
+QList<CoreIdentity> PostgreSqlStorage::identities(UserId user) {
+  QList<CoreIdentity> identities;
+
+  QSqlDatabase db = logDb();
+  if(!beginReadOnlyTransaction(db)) {
+    qWarning() << "PostgreSqlStorage::identites(): cannot start read only transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return identities;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("select_identities"));
+  query.bindValue(":userid", user.toInt());
+
+  QSqlQuery nickQuery(db);
+  nickQuery.prepare(queryString("select_nicks"));
+
+  safeExec(query);
+
+  while(query.next()) {
+    CoreIdentity identity(IdentityId(query.value(0).toInt()));
+
+    identity.setIdentityName(query.value(1).toString());
+    identity.setRealName(query.value(2).toString());
+    identity.setAwayNick(query.value(3).toString());
+    identity.setAwayNickEnabled(!!query.value(4).toInt());
+    identity.setAwayReason(query.value(5).toString());
+    identity.setAwayReasonEnabled(!!query.value(6).toInt());
+    identity.setAutoAwayEnabled(!!query.value(7).toInt());
+    identity.setAutoAwayTime(query.value(8).toInt());
+    identity.setAutoAwayReason(query.value(9).toString());
+    identity.setAutoAwayReasonEnabled(!!query.value(10).toInt());
+    identity.setDetachAwayEnabled(!!query.value(11).toInt());
+    identity.setDetachAwayReason(query.value(12).toString());
+    identity.setDetachAwayReasonEnabled(!!query.value(13).toInt());
+    identity.setIdent(query.value(14).toString());
+    identity.setKickReason(query.value(15).toString());
+    identity.setPartReason(query.value(16).toString());
+    identity.setQuitReason(query.value(17).toString());
+#ifdef HAVE_SSL
+    identity.setSslCert(query.value(18).toByteArray());
+    identity.setSslKey(query.value(19).toByteArray());
+#endif
+
+    nickQuery.bindValue(":identityid", identity.id().toInt());
+    QList<QString> nicks;
+    safeExec(nickQuery);
+    watchQuery(nickQuery);
+    while(nickQuery.next()) {
+      nicks << nickQuery.value(0).toString();
+    }
+    identity.setNicks(nicks);
+    identities << identity;
+  }
+  db.commit();
+  return identities;
+}
+
+NetworkId PostgreSqlStorage::createNetwork(UserId user, const NetworkInfo &info) {
+  NetworkId networkId;
+
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::createNetwork(): failed to begin transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return false;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("insert_network"));
+  query.bindValue(":userid", user.toInt());
+  bindNetworkInfo(query, info);
+  safeExec(query);
+  if(query.lastError().isValid()) {
+    watchQuery(query);
+    db.rollback();
+    return NetworkId();
+  }
+
+  qDebug() << "createNet:" << query.first() << query.value(0).toInt();
+  networkId = query.value(0).toInt();
+
+  if(!networkId.isValid()) {
+    watchQuery(query);
+    db.rollback();
+    return NetworkId();
+  }
+
+  QSqlQuery insertServersQuery(db);
+  insertServersQuery.prepare(queryString("insert_server"));
+  foreach(Network::Server server, info.serverList) {
+    insertServersQuery.bindValue(":userid", user.toInt());
+    insertServersQuery.bindValue(":networkid", networkId.toInt());
+    bindServerInfo(insertServersQuery, server);
+    safeExec(insertServersQuery);
+    if(!watchQuery(insertServersQuery)) {
+      db.rollback();
+      return NetworkId();
+    }
+  }
+
+  if(!db.commit()) {
+    qWarning() << "PostgreSqlStorage::updateNetwork(): commiting data failed!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return NetworkId();
+  }
+  return networkId;
+}
+
+void PostgreSqlStorage::bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info) {
+  query.bindValue(":networkname", info.networkName);
+  query.bindValue(":identityid", info.identity.toInt());
+  query.bindValue(":encodingcodec", QString(info.codecForEncoding));
+  query.bindValue(":decodingcodec", QString(info.codecForDecoding));
+  query.bindValue(":servercodec", QString(info.codecForServer));
+  query.bindValue(":userandomserver", info.useRandomServer);
+  query.bindValue(":perform", info.perform.join("\n"));
+  query.bindValue(":useautoidentify", info.useAutoIdentify);
+  query.bindValue(":autoidentifyservice", info.autoIdentifyService);
+  query.bindValue(":autoidentifypassword", info.autoIdentifyPassword);
+  query.bindValue(":useautoreconnect", info.useAutoReconnect);
+  query.bindValue(":autoreconnectinterval", info.autoReconnectInterval);
+  query.bindValue(":autoreconnectretries", info.autoReconnectRetries);
+  query.bindValue(":unlimitedconnectretries", info.unlimitedReconnectRetries);
+  query.bindValue(":rejoinchannels", info.rejoinChannels);
+  if(info.networkId.isValid())
+    query.bindValue(":networkid", info.networkId.toInt());
+}
+
+void PostgreSqlStorage::bindServerInfo(QSqlQuery &query, const Network::Server &server) {
+  query.bindValue(":hostname", server.host);
+  query.bindValue(":port", server.port);
+  query.bindValue(":password", server.password);
+  query.bindValue(":ssl", server.useSsl);
+  query.bindValue(":sslversion", server.sslVersion);
+  query.bindValue(":useproxy", server.useProxy);
+  query.bindValue(":proxytype", server.proxyType);
+  query.bindValue(":proxyhost", server.proxyHost);
+  query.bindValue(":proxyport", server.proxyPort);
+  query.bindValue(":proxyuser", server.proxyUser);
+  query.bindValue(":proxypass", server.proxyPass);
+}
+
+bool PostgreSqlStorage::updateNetwork(UserId user, const NetworkInfo &info) {
+  if(!isValidNetwork(user, info.networkId))
+     return false;
+
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::updateNetwork(): failed to begin transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return false;
+  }
+
+  QSqlQuery updateQuery(db);
+  updateQuery.prepare(queryString("update_network"));
+  bindNetworkInfo(updateQuery, info);
+  safeExec(updateQuery);
+  if(!watchQuery(updateQuery)) {
+    db.rollback();
+    return false;
+  }
+
+  QSqlQuery dropServersQuery(db);
+  dropServersQuery.prepare("DELETE FROM ircserver WHERE networkid = :networkid");
+  dropServersQuery.bindValue(":networkid", info.networkId.toInt());
+  safeExec(dropServersQuery);
+  if(!watchQuery(dropServersQuery)) {
+    db.rollback();
+    return false;
+  }
+
+  QSqlQuery insertServersQuery(db);
+  insertServersQuery.prepare(queryString("insert_server"));
+  foreach(Network::Server server, info.serverList) {
+    insertServersQuery.bindValue(":userid", user.toInt());
+    insertServersQuery.bindValue(":networkid", info.networkId.toInt());
+    bindServerInfo(insertServersQuery, server);
+    safeExec(insertServersQuery);
+    if(!watchQuery(insertServersQuery)) {
+      db.rollback();
+      return false;
+    }
+  }
+
+  if(!db.commit()) {
+    qWarning() << "PostgreSqlStorage::updateNetwork(): commiting data failed!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return false;
+  }
+  return true;
+}
+
+bool PostgreSqlStorage::removeNetwork(UserId user, const NetworkId &networkId) {
+  if(!isValidNetwork(user, networkId))
+     return false;
+
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::removeNetwork(): cannot start transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return false;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("delete_network"));
+  query.bindValue(":networkid", networkId.toInt());
+  safeExec(query);
+  if(!watchQuery(query)) {
+    db.rollback();
+    return false;
+  }
+
+  db.commit();
+  return true;
+}
+
+QList<NetworkInfo> PostgreSqlStorage::networks(UserId user) {
+  QList<NetworkInfo> nets;
+
+  QSqlDatabase db = logDb();
+  if(!beginReadOnlyTransaction(db)) {
+    qWarning() << "PostgreSqlStorage::networks(): cannot start read only transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return nets;
+  }
+  
+  QSqlQuery networksQuery(db);
+  networksQuery.prepare(queryString("select_networks_for_user"));
+  networksQuery.bindValue(":userid", user.toInt());
+
+  QSqlQuery serversQuery(db);
+  serversQuery.prepare(queryString("select_servers_for_network"));
+
+  safeExec(networksQuery);
+  if(!watchQuery(networksQuery)) {
+    db.rollback();
+    return nets;
+  }
+
+  while(networksQuery.next()) {
+    NetworkInfo net;
+    net.networkId = networksQuery.value(0).toInt();
+    net.networkName = networksQuery.value(1).toString();
+    net.identity = networksQuery.value(2).toInt();
+    net.codecForServer = networksQuery.value(3).toString().toAscii();
+    net.codecForEncoding = networksQuery.value(4).toString().toAscii();
+    net.codecForDecoding = networksQuery.value(5).toString().toAscii();
+    net.useRandomServer = networksQuery.value(6).toBool();
+    net.perform = networksQuery.value(7).toString().split("\n");
+    net.useAutoIdentify = networksQuery.value(8).toBool();
+    net.autoIdentifyService = networksQuery.value(9).toString();
+    net.autoIdentifyPassword = networksQuery.value(10).toString();
+    net.useAutoReconnect = networksQuery.value(11).toBool();
+    net.autoReconnectInterval = networksQuery.value(12).toUInt();
+    net.autoReconnectRetries = networksQuery.value(13).toInt();
+    net.unlimitedReconnectRetries = networksQuery.value(14).toBool();
+    net.rejoinChannels = networksQuery.value(15).toBool();
+
+    serversQuery.bindValue(":networkid", net.networkId.toInt());
+    safeExec(serversQuery);
+    if(!watchQuery(serversQuery)) {
+      db.rollback();
+      return nets;
+    }
+
+    Network::ServerList servers;
+    while(serversQuery.next()) {
+      Network::Server server;
+      server.host = serversQuery.value(0).toString();
+      server.port = serversQuery.value(1).toUInt();
+      server.password = serversQuery.value(2).toString();
+      server.useSsl = serversQuery.value(3).toBool();
+      server.sslVersion = serversQuery.value(4).toInt();
+      server.useProxy = serversQuery.value(5).toBool();
+      server.proxyType = serversQuery.value(6).toInt();
+      server.proxyHost = serversQuery.value(7).toString();
+      server.proxyPort = serversQuery.value(8).toUInt();
+      server.proxyUser = serversQuery.value(9).toString();
+      server.proxyPass = serversQuery.value(10).toString();
+      servers << server;
+    }
+    net.serverList = servers;
+    nets << net;
+  }
+  db.commit();
+  return nets;
+}
+
+bool PostgreSqlStorage::isValidNetwork(UserId user, const NetworkId &networkId) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_networkExists"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkid", networkId.toInt());
+  safeExec(query);
+
+  watchQuery(query);
+  if(!query.first())
+    return false;
+
+  Q_ASSERT(!query.next());
+  return true;
+}
+
+bool PostgreSqlStorage::isValidBuffer(const UserId &user, const BufferId &bufferId) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_bufferExists"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":bufferid", bufferId.toInt());
+  safeExec(query);
+
+  watchQuery(query);
+  if(!query.first())
+    return false;
+
+  Q_ASSERT(!query.next());
+  return true;
+}
+
+QList<NetworkId> PostgreSqlStorage::connectedNetworks(UserId user) {
+  QList<NetworkId> connectedNets;
+
+  QSqlDatabase db = logDb();
+  if(!beginReadOnlyTransaction(db)) {
+    qWarning() << "PostgreSqlStorage::connectedNetworks(): cannot start read only transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return connectedNets;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("select_connected_networks"));
+  query.bindValue(":userid", user.toInt());
+  safeExec(query);
+  watchQuery(query);
+
+  while(query.next()) {
+    connectedNets << query.value(0).toInt();
+  }
+
+  db.commit();
+  return connectedNets;
+}
+
+void PostgreSqlStorage::setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_network_connected"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkid", networkId.toInt());
+  query.bindValue(":connected", isConnected);
+  safeExec(query);
+  watchQuery(query);
+}
+
+QHash<QString, QString> PostgreSqlStorage::persistentChannels(UserId user, const NetworkId &networkId) {
+  QHash<QString, QString> persistentChans;
+
+  QSqlDatabase db = logDb();
+  if(!beginReadOnlyTransaction(db)) {
+    qWarning() << "PostgreSqlStorage::persistentChannels(): cannot start read only transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return persistentChans;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("select_persistent_channels"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkid", networkId.toInt());
+  safeExec(query);
+  watchQuery(query);
+
+  while(query.next()) {
+    persistentChans[query.value(0).toString()] = query.value(1).toString();
+  }
+
+  db.commit();
+  return persistentChans;
+}
+
+void PostgreSqlStorage::setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_buffer_persistent_channel"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkId", networkId.toInt());
+  query.bindValue(":buffercname", channel.toLower());
+  query.bindValue(":joined", isJoined);
+  safeExec(query);
+  watchQuery(query);
+}
+
+void PostgreSqlStorage::setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_buffer_set_channel_key"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkId", networkId.toInt());
+  query.bindValue(":buffercname", channel.toLower());
+  query.bindValue(":key", key);
+  safeExec(query);
+  watchQuery(query);
+}
+
+QString PostgreSqlStorage::awayMessage(UserId user, NetworkId networkId) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_network_awaymsg"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkid", networkId.toInt());
+  safeExec(query);
+  watchQuery(query);
+  QString awayMsg;
+  if(query.first())
+    awayMsg = query.value(0).toString();
+  return awayMsg;
+}
+
+void PostgreSqlStorage::setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_network_set_awaymsg"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkid", networkId.toInt());
+  query.bindValue(":awaymsg", awayMsg);
+  safeExec(query);
+  watchQuery(query);
+}
+
+QString PostgreSqlStorage::userModes(UserId user, NetworkId networkId) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_network_usermode"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkid", networkId.toInt());
+  safeExec(query);
+  watchQuery(query);
+  QString modes;
+  if(query.first())
+    modes = query.value(0).toString();
+  return modes;
+}
+
+void PostgreSqlStorage::setUserModes(UserId user, NetworkId networkId, const QString &userModes) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_network_set_usermode"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":networkid", networkId.toInt());
+  query.bindValue(":usermode", userModes);
+  safeExec(query);
+  watchQuery(query);
+}
+
+BufferInfo PostgreSqlStorage::bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer, bool create) {
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::bufferInfo(): cannot start read only transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return BufferInfo();
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("select_bufferByName"));
+  query.bindValue(":networkid", networkId.toInt());
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":buffercname", buffer.toLower());
+  safeExec(query);
+
+  if(query.first()) {
+    BufferInfo bufferInfo = BufferInfo(query.value(0).toInt(), networkId, (BufferInfo::Type)query.value(1).toInt(), 0, buffer);
+    if(query.next()) {
+      qCritical() << "PostgreSqlStorage::getBufferInfo(): received more then one Buffer!";
+      qCritical() << "         Query:" << query.lastQuery();
+      qCritical() << "  bound Values:";
+      QList<QVariant> list = query.boundValues().values();
+      for (int i = 0; i < list.size(); ++i)
+       qCritical() << i << ":" << list.at(i).toString().toAscii().data();
+      Q_ASSERT(false);
+    }
+    db.commit();
+    return bufferInfo;
+  }
+
+  if(!create) {
+    db.rollback();
+    return BufferInfo();
+  }
+
+  QSqlQuery createQuery(db);
+  createQuery.prepare(queryString("insert_buffer"));
+  createQuery.bindValue(":userid", user.toInt());
+  createQuery.bindValue(":networkid", networkId.toInt());
+  createQuery.bindValue(":buffertype", (int)type);
+  createQuery.bindValue(":buffername", buffer);
+  createQuery.bindValue(":buffercname", buffer.toLower());
+  safeExec(createQuery);
+
+  if(createQuery.lastError().isValid()) {
+    qWarning() << "PostgreSqlStorage::bufferInfo(): unable to create buffer";
+    watchQuery(createQuery);
+    db.rollback();
+    return BufferInfo();
+  }
+
+  createQuery.first();
+
+  BufferInfo bufferInfo = BufferInfo(createQuery.value(0).toInt(), networkId, type, 0, buffer);
+  db.commit();
+  return bufferInfo;
+}
+
+BufferInfo PostgreSqlStorage::getBufferInfo(UserId user, const BufferId &bufferId) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("select_buffer_by_id"));
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":bufferid", bufferId.toInt());
+  safeExec(query);
+  if(!watchQuery(query))
+    return BufferInfo();
+
+  if(!query.first())
+    return BufferInfo();
+
+  BufferInfo bufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), 0, query.value(4).toString());
+  Q_ASSERT(!query.next());
+
+  return bufferInfo;
+}
+
+QList<BufferInfo> PostgreSqlStorage::requestBuffers(UserId user) {
+  QList<BufferInfo> bufferlist;
+
+  QSqlDatabase db = logDb();
+  if(!beginReadOnlyTransaction(db)) {
+    qWarning() << "PostgreSqlStorage::requestBuffers(): cannot start read only transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return bufferlist;
+  }
+  
+  QSqlQuery query(db);
+  query.prepare(queryString("select_buffers"));
+  query.bindValue(":userid", user.toInt());
+
+  safeExec(query);
+  watchQuery(query);
+  while(query.next()) {
+    bufferlist << BufferInfo(query.value(0).toInt(), query.value(1).toInt(), (BufferInfo::Type)query.value(2).toInt(), query.value(3).toInt(), query.value(4).toString());
+  }
+  db.commit();
+  return bufferlist;
+}
+
+QList<BufferId> PostgreSqlStorage::requestBufferIdsForNetwork(UserId user, NetworkId networkId) {
+  QList<BufferId> bufferList;
+
+  QSqlDatabase db = logDb();
+  if(!beginReadOnlyTransaction(db)) {
+    qWarning() << "PostgreSqlStorage::requestBufferIdsForNetwork(): cannot start read only transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return bufferList;
+  }
+  
+  QSqlQuery query(db);
+  query.prepare(queryString("select_buffers_for_network"));
+  query.bindValue(":networkid", networkId.toInt());
+  query.bindValue(":userid", user.toInt());
+
+  safeExec(query);
+  watchQuery(query);
+  while(query.next()) {
+    bufferList << BufferId(query.value(0).toInt());
+  }
+  db.commit();
+  return bufferList;
+}
+
+bool PostgreSqlStorage::removeBuffer(const UserId &user, const BufferId &bufferId) {
+  if(!isValidBuffer(user, bufferId))
+    return false;
+
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::removeBuffer(): cannot start transaction!";
+    return false;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("delete_buffer_for_bufferid"));
+  query.bindValue(":bufferid", bufferId.toInt());
+  safeExec(query);
+  if(!watchQuery(query)) {
+    db.rollback();
+    return false;
+  }
+  db.commit();
+  return true;
+}
+
+bool PostgreSqlStorage::renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) {
+  if(!isValidBuffer(user, bufferId))
+    return false;
+
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_buffer_name"));
+  query.bindValue(":buffername", newName);
+  query.bindValue(":buffercname", newName.toLower());
+  query.bindValue(":bufferid", bufferId.toInt());
+  safeExec(query);
+  if(query.lastError().isValid()) {
+    return false;
+  }
+  return true;
+}
+
+bool PostgreSqlStorage::mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) {
+  if(!isValidBuffer(user, bufferId1) || !isValidBuffer(user, bufferId2))
+    return false;
+
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::mergeBuffersPermanently(): cannot start transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return false;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("update_backlog_bufferid"));
+  query.bindValue(":oldbufferid", bufferId2.toInt());
+  query.bindValue(":newbufferid", bufferId1.toInt());
+  safeExec(query);
+  if(!watchQuery(query)) {
+    db.rollback();
+    return false;
+  }
+
+  QSqlQuery delBufferQuery(logDb());
+  delBufferQuery.prepare(queryString("delete_buffer_for_bufferid"));
+  delBufferQuery.bindValue(":bufferid", bufferId2.toInt());
+  safeExec(delBufferQuery);
+  if(!watchQuery(delBufferQuery)) {
+    db.rollback();
+    return false;
+  }
+
+  db.commit();
+  return true;
+}
+
+void PostgreSqlStorage::setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) {
+  QSqlQuery query(logDb());
+  query.prepare(queryString("update_buffer_lastseen"));
+
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":bufferid", bufferId.toInt());
+  query.bindValue(":lastseenmsgid", msgId.toInt());
+  safeExec(query);
+  watchQuery(query);
+}
+
+QHash<BufferId, MsgId> PostgreSqlStorage::bufferLastSeenMsgIds(UserId user) {
+  QHash<BufferId, MsgId> lastSeenHash;
+
+  QSqlDatabase db = logDb();
+  if(!beginReadOnlyTransaction(db)) {
+    qWarning() << "PostgreSqlStorage::bufferLastSeenMsgIds(): cannot start read only transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return lastSeenHash;
+  }
+
+  QSqlQuery query(db);
+  query.prepare(queryString("select_buffer_lastseen_messages"));
+  query.bindValue(":userid", user.toInt());
+  safeExec(query);
+  if(!watchQuery(query)) {
+    db.rollback();
+    return lastSeenHash;
+  }
+
+  while(query.next()) {
+    lastSeenHash[query.value(0).toInt()] = query.value(1).toInt();
+  }
+
+  db.commit();
+  return lastSeenHash;
+}
+
+MsgId PostgreSqlStorage::logMessage(Message msg) {
+  QSqlDatabase db = logDb();
+  if(!db.transaction()) {
+    qWarning() << "PostgreSqlStorage::logMessage(): cannot start transaction!";
+    qWarning() << " -" << qPrintable(db.lastError().text());
+    return false;
+  }
+
+  QSqlQuery logMessageQuery(db);
+  logMessageQuery.prepare(queryString("insert_message"));
+  logMessageQuery.bindValue(":time", msg.timestamp().toTime_t());
+  logMessageQuery.bindValue(":bufferid", msg.bufferInfo().bufferId().toInt());
+  logMessageQuery.bindValue(":type", msg.type());
+  logMessageQuery.bindValue(":flags", (int)msg.flags());
+  logMessageQuery.bindValue(":sender", msg.sender());
+  logMessageQuery.bindValue(":message", msg.contents());
+  safeExec(logMessageQuery);
+
+  if(logMessageQuery.lastError().isValid()) {
+    // first we need to reset the transaction
+    db.rollback();
+    db.transaction(); 
+
+    QSqlQuery addSenderQuery(db);
+    addSenderQuery.prepare(queryString("insert_sender"));
+    addSenderQuery.bindValue(":sender", msg.sender());
+    safeExec(addSenderQuery);
+    safeExec(logMessageQuery);
+
+    if(!watchQuery(logMessageQuery)) {
+      db.rollback();
+      return MsgId();
+    }
+  }
+
+  logMessageQuery.first();
+  MsgId msgId = logMessageQuery.value(0).toInt();
+  db.commit();
+
+  Q_ASSERT(msgId.isValid());
+  return msgId;
+}
+
+QList<Message> PostgreSqlStorage::requestMsgs(UserId user, BufferId bufferId, MsgId first, MsgId last, int limit) {
+  QList<Message> messagelist;
+
+  BufferInfo bufferInfo = getBufferInfo(user, bufferId);
+  if(!bufferInfo.isValid())
+    return messagelist;
+
+  QSqlQuery query(logDb());
+  
+  if(last == -1 && first == -1) {
+    query.prepare(queryString("select_messagesNewestK"));
+  } else if(last == -1) {
+    query.prepare(queryString("select_messagesNewerThan"));
+    query.bindValue(":firstmsg", first.toInt());
+  } else {
+    query.prepare(queryString("select_messages"));
+    query.bindValue(":lastmsg", last.toInt());
+    query.bindValue(":firstmsg", first.toInt());
+  }
+
+  query.bindValue(":bufferid", bufferId.toInt());
+  query.bindValue(":limit", limit);
+  safeExec(query);
+
+  watchQuery(query);
+
+  while(query.next()) {
+    Message msg(QDateTime::fromTime_t(query.value(1).toInt()),
+                bufferInfo,
+                (Message::Type)query.value(2).toUInt(),
+                query.value(5).toString(),
+                query.value(4).toString(),
+                (Message::Flags)query.value(3).toUInt());
+    msg.setMsgId(query.value(0).toInt());
+    messagelist << msg;
+  }
+  return messagelist;
+}
+
+QList<Message> PostgreSqlStorage::requestAllMsgs(UserId user, MsgId first, MsgId last, int limit) {
+  QList<Message> messagelist;
+
+  QHash<BufferId, BufferInfo> bufferInfoHash;
+  foreach(BufferInfo bufferInfo, requestBuffers(user)) {
+    bufferInfoHash[bufferInfo.bufferId()] = bufferInfo;
+  }
+
+  QSqlQuery query(logDb());
+  if(last == -1) {
+    query.prepare(queryString("select_messagesAllNew"));
+  } else {
+    query.prepare(queryString("select_messagesAll"));
+    query.bindValue(":lastmsg", last.toInt());
+  }
+  query.bindValue(":userid", user.toInt());
+  query.bindValue(":firstmsg", first.toInt());
+  query.bindValue(":limit", limit);
+  safeExec(query);
+
+  watchQuery(query);
+
+  while(query.next()) {
+    Message msg(QDateTime::fromTime_t(query.value(2).toInt()),
+                bufferInfoHash[query.value(1).toInt()],
+                (Message::Type)query.value(3).toUInt(),
+                query.value(6).toString(),
+                query.value(5).toString(),
+                (Message::Flags)query.value(4).toUInt());
+    msg.setMsgId(query.value(0).toInt());
+    messagelist << msg;
+  }
+
+  return messagelist;
+}
+
+// void PostgreSqlStorage::safeExec(QSqlQuery &query) {
+//   qDebug() << "PostgreSqlStorage::safeExec";
+//   qDebug() << "   executing:\n" << query.executedQuery();
+//   qDebug() << "   bound Values:";
+//   QList<QVariant> list = query.boundValues().values();
+//   for (int i = 0; i < list.size(); ++i)
+//     qCritical() << i << ": " << list.at(i).toString().toAscii().data();
+
+//   query.exec();
+
+//   qDebug() << "Success:" << !query.lastError().isValid();
+//   qDebug();
+
+//   if(!query.lastError().isValid())
+//     return;
+
+//   qDebug() << "==================== ERROR ====================";
+//   watchQuery(query);
+//   qDebug() << "===============================================";
+//   qDebug();
+//   return;
+// }
+
+bool PostgreSqlStorage::beginReadOnlyTransaction(QSqlDatabase &db) {
+  QSqlQuery query = db.exec("BEGIN TRANSACTION READ ONLY");
+  return !query.lastError().isValid();
+}
diff --git a/src/core/postgresqlstorage.h b/src/core/postgresqlstorage.h
new file mode 100644 (file)
index 0000000..d83b4cc
--- /dev/null
@@ -0,0 +1,131 @@
+/***************************************************************************
+ *   Copyright (C) 2005-09 by the Quassel Project                          *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) version 3.                                           *
+ *                                                                         *
+ *   This program 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 General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef POSTGRESQLSTORAGE_H
+#define POSTGRESQLSTORAGE_H
+
+#include "abstractsqlstorage.h"
+
+#include <QSqlDatabase>
+#include <QSqlQuery>
+
+class PostgreSqlStorage : public AbstractSqlStorage {
+  Q_OBJECT
+
+public:
+  PostgreSqlStorage(QObject *parent = 0);
+  virtual ~PostgreSqlStorage();
+
+public slots:
+  /* General */
+
+  bool isAvailable() const;
+  QString displayName() const;
+  QString description() const;
+  QVariantMap setupKeys() const;
+  
+  // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc
+
+  /* User handling */
+
+  virtual UserId addUser(const QString &user, const QString &password);
+  virtual void updateUser(UserId user, const QString &password);
+  virtual void renameUser(UserId user, const QString &newName);
+  virtual UserId validateUser(const QString &user, const QString &password);
+  virtual UserId internalUser();
+  virtual void delUser(UserId user);
+  virtual void setUserSetting(UserId userId, const QString &settingName, const QVariant &data);
+  virtual QVariant getUserSetting(UserId userId, const QString &settingName, const QVariant &defaultData = QVariant());
+
+  /* Identity handling */
+  virtual IdentityId createIdentity(UserId user, CoreIdentity &identity);
+  virtual bool updateIdentity(UserId user, const CoreIdentity &identity);
+  virtual void removeIdentity(UserId user, IdentityId identityId);
+  virtual QList<CoreIdentity> identities(UserId user);
+
+  /* Network handling */
+  virtual NetworkId createNetwork(UserId user, const NetworkInfo &info);
+  virtual bool updateNetwork(UserId user, const NetworkInfo &info);
+  virtual bool removeNetwork(UserId user, const NetworkId &networkId);
+  virtual QList<NetworkInfo> networks(UserId user);
+  virtual QList<NetworkId> connectedNetworks(UserId user);
+  virtual void setNetworkConnected(UserId user, const NetworkId &networkId, bool isConnected);
+
+  /* persistent channels */
+  virtual QHash<QString, QString> persistentChannels(UserId user, const NetworkId &networkId);
+  virtual void setChannelPersistent(UserId user, const NetworkId &networkId, const QString &channel, bool isJoined);
+  virtual void setPersistentChannelKey(UserId user, const NetworkId &networkId, const QString &channel, const QString &key);
+
+  /* persistent user states */
+  virtual QString awayMessage(UserId user, NetworkId networkId);
+  virtual void setAwayMessage(UserId user, NetworkId networkId, const QString &awayMsg);
+  virtual QString userModes(UserId user, NetworkId networkId);
+  virtual void setUserModes(UserId user, NetworkId networkId, const QString &userModes);
+  
+  /* Buffer handling */
+  virtual BufferInfo bufferInfo(UserId user, const NetworkId &networkId, BufferInfo::Type type, const QString &buffer = "", bool create = true);
+  virtual BufferInfo getBufferInfo(UserId user, const BufferId &bufferId);
+  virtual QList<BufferInfo> requestBuffers(UserId user);
+  virtual QList<BufferId> requestBufferIdsForNetwork(UserId user, NetworkId networkId);
+  virtual bool removeBuffer(const UserId &user, const BufferId &bufferId);
+  virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName);
+  virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2);
+  virtual void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId);
+  virtual QHash<BufferId, MsgId> bufferLastSeenMsgIds(UserId user);
+
+  /* Message handling */
+
+  virtual MsgId logMessage(Message msg);
+  virtual QList<Message> requestMsgs(UserId user, BufferId bufferId, MsgId first = -1, MsgId last = -1, int limit = -1);
+  virtual QList<Message> requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1);
+
+protected:
+  virtual void setConnectionProperties(const QVariantMap &properties);
+  inline virtual QString driverName() { return "QPSQL"; }
+  inline virtual QString hostName() { return _hostName; }
+  inline virtual int port() { return _port; }
+  inline virtual QString databaseName() { return _databaseName; }
+  inline virtual QString userName() { return _userName; }
+  inline virtual QString password() { return _password; }
+  virtual int installedSchemaVersion();
+  virtual bool updateSchemaVersion(int newVersion);
+  virtual bool setupSchemaVersion(int version);
+  void safeExec(QSqlQuery &query);
+  bool beginReadOnlyTransaction(QSqlDatabase &db);
+
+private:
+  bool isValidNetwork(UserId user, const NetworkId &networkId);
+  bool isValidBuffer(const UserId &user, const BufferId &bufferId);
+
+  void bindNetworkInfo(QSqlQuery &query, const NetworkInfo &info);
+  void bindServerInfo(QSqlQuery &query, const Network::Server &server);
+
+  QString _hostName;
+  int _port;
+  QString _databaseName;
+  QString _userName;
+  QString _password;
+  
+  static int _maxRetryCount;
+};
+
+inline void PostgreSqlStorage::safeExec(QSqlQuery &query) { query.exec(); }
+
+#endif
index 7c58469..2890a0e 100644 (file)
@@ -1,5 +1,75 @@
 <!DOCTYPE RCC><RCC version="1.0">
 <qresource>
 <!DOCTYPE RCC><RCC version="1.0">
 <qresource>
+    <file>./SQL/PostgreSQL/14/delete_backlog_by_uid.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_backlog_for_buffer.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_backlog_for_network.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_buffer_for_bufferid.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_buffers_by_uid.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_buffers_for_network.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_identity.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_ircservers_for_network.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_network.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_networks_by_uid.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_nicks.sql</file>
+    <file>./SQL/PostgreSQL/14/delete_quasseluser.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_buffer.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_identity.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_message.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_network.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_nick.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_quasseluser.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_sender.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_server.sql</file>
+    <file>./SQL/PostgreSQL/14/insert_user_setting.sql</file>
+    <file>./SQL/PostgreSQL/14/select_authuser.sql</file>
+    <file>./SQL/PostgreSQL/14/select_buffer_by_id.sql</file>
+    <file>./SQL/PostgreSQL/14/select_buffer_lastseen_messages.sql</file>
+    <file>./SQL/PostgreSQL/14/select_bufferByName.sql</file>
+    <file>./SQL/PostgreSQL/14/select_bufferExists.sql</file>
+    <file>./SQL/PostgreSQL/14/select_buffers.sql</file>
+    <file>./SQL/PostgreSQL/14/select_buffers_for_network.sql</file>
+    <file>./SQL/PostgreSQL/14/select_checkidentity.sql</file>
+    <file>./SQL/PostgreSQL/14/select_connected_networks.sql</file>
+    <file>./SQL/PostgreSQL/14/select_identities.sql</file>
+    <file>./SQL/PostgreSQL/14/select_internaluser.sql</file>
+    <file>./SQL/PostgreSQL/14/select_messages.sql</file>
+    <file>./SQL/PostgreSQL/14/select_messagesAll.sql</file>
+    <file>./SQL/PostgreSQL/14/select_messagesAllNew.sql</file>
+    <file>./SQL/PostgreSQL/14/select_messagesNewerThan.sql</file>
+    <file>./SQL/PostgreSQL/14/select_messagesNewestK.sql</file>
+    <file>./SQL/PostgreSQL/14/select_network_awaymsg.sql</file>
+    <file>./SQL/PostgreSQL/14/select_network_usermode.sql</file>
+    <file>./SQL/PostgreSQL/14/select_networkExists.sql</file>
+    <file>./SQL/PostgreSQL/14/select_networks_for_user.sql</file>
+    <file>./SQL/PostgreSQL/14/select_nicks.sql</file>
+    <file>./SQL/PostgreSQL/14/select_persistent_channels.sql</file>
+    <file>./SQL/PostgreSQL/14/select_servers_for_network.sql</file>
+    <file>./SQL/PostgreSQL/14/select_user_setting.sql</file>
+    <file>./SQL/PostgreSQL/14/select_userid.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_000_quasseluser.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_010_sender.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_020_identity.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_030_identity_nick.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_040_network.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_050_buffer.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_060_backlog.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_070_coreinfo.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_080_ircservers.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_090_backlog_idx.sql</file>
+    <file>./SQL/PostgreSQL/14/setup_100_user_setting.sql</file>
+    <file>./SQL/PostgreSQL/14/update_backlog_bufferid.sql</file>
+    <file>./SQL/PostgreSQL/14/update_buffer_lastseen.sql</file>
+    <file>./SQL/PostgreSQL/14/update_buffer_name.sql</file>
+    <file>./SQL/PostgreSQL/14/update_buffer_persistent_channel.sql</file>
+    <file>./SQL/PostgreSQL/14/update_buffer_set_channel_key.sql</file>
+    <file>./SQL/PostgreSQL/14/update_identity.sql</file>
+    <file>./SQL/PostgreSQL/14/update_network.sql</file>
+    <file>./SQL/PostgreSQL/14/update_network_connected.sql</file>
+    <file>./SQL/PostgreSQL/14/update_network_set_awaymsg.sql</file>
+    <file>./SQL/PostgreSQL/14/update_network_set_usermode.sql</file>
+    <file>./SQL/PostgreSQL/14/update_user_setting.sql</file>
+    <file>./SQL/PostgreSQL/14/update_username.sql</file>
+    <file>./SQL/PostgreSQL/14/update_userpassword.sql</file>
     <file>./SQL/SQLite/1/upgrade_000_drop_coreinfo.sql</file>
     <file>./SQL/SQLite/1/upgrade_010_create_coreinfo.sql</file>
     <file>./SQL/SQLite/1/upgrade_020_update_schemaversion.sql</file>
     <file>./SQL/SQLite/1/upgrade_000_drop_coreinfo.sql</file>
     <file>./SQL/SQLite/1/upgrade_010_create_coreinfo.sql</file>
     <file>./SQL/SQLite/1/upgrade_020_update_schemaversion.sql</file>
index fbb366f..feb2c5a 100644 (file)
@@ -39,6 +39,7 @@ public slots:
 
   bool isAvailable() const;
   QString displayName() const;
 
   bool isAvailable() const;
   QString displayName() const;
+  inline QVariantMap setupKeys() const { return QVariantMap(); }
   QString description() const;
 
   // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc
   QString description() const;
 
   // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc
@@ -97,6 +98,7 @@ public slots:
   virtual QList<Message> requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1);
 
 protected:
   virtual QList<Message> requestAllMsgs(UserId user, MsgId first = -1, MsgId last = -1, int limit = -1);
 
 protected:
+  inline virtual void setConnectionProperties(const QVariantMap & /* properties */) {}
   inline virtual QString driverName() { return "QSQLITE"; }
   inline virtual QString databaseName() { return backlogFile(); }
   virtual int installedSchemaVersion();
   inline virtual QString driverName() { return "QSQLITE"; }
   inline virtual QString databaseName() { return backlogFile(); }
   virtual int installedSchemaVersion();
index 1cb2ee8..17fdd70 100644 (file)
@@ -59,6 +59,10 @@ public slots:
   /** \return A string that can be displayed by the client to describe the storage backend */
   virtual QString description() const = 0;
 
   /** \return A string that can be displayed by the client to describe the storage backend */
   virtual QString description() const = 0;
 
+  //! Returns a map where the keys are required properties to use the storage backend
+  /*  the values are QVariants with default values */
+  virtual QVariantMap setupKeys() const = 0;
+
   //! Setup the storage provider.
   /** This prepares the storage provider (e.g. create tables, etc.) for use within Quassel.
    *  \param settings   Hostname, port, username, password, ...
   //! Setup the storage provider.
   /** This prepares the storage provider (e.g. create tables, etc.) for use within Quassel.
    *  \param settings   Hostname, port, username, password, ...
@@ -176,13 +180,6 @@ public slots:
    */
   virtual QList<NetworkInfo> networks(UserId user) = 0;
   
    */
   virtual QList<NetworkInfo> networks(UserId user) = 0;
   
-  //! Get the unique NetworkId of the network for a user.
-  /** \param user    The core user who owns this network
-   *  \param network The network name
-   *  \return The NetworkId corresponding to the given network, or 0 if not found
-   */
-  virtual NetworkId getNetworkId(UserId user, const QString &network) = 0;
-
   //! Get a list of Networks to restore
   /** Return a list of networks the user was connected at the time of core shutdown
    *  \note This method is threadsafe.
   //! Get a list of Networks to restore
   /** Return a list of networks the user was connected at the time of core shutdown
    *  \note This method is threadsafe.
index bc2ebf3..030af57 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <QDebug>
 #include <QAbstractButton>
 
 #include <QDebug>
 #include <QAbstractButton>
+#include <QFormLayout>
+#include <QSpinBox>
 
 #include "coreconfigwizard.h"
 #include "iconloader.h"
 
 #include "coreconfigwizard.h"
 #include "iconloader.h"
@@ -30,7 +32,7 @@ CoreConfigWizard::CoreConfigWizard(const QList<QVariant> &backends, QWidget *par
   setPage(AdminUserPage, new CoreConfigWizardPages::AdminUserPage(this));
   setPage(StorageSelectionPage, new CoreConfigWizardPages::StorageSelectionPage(_backends, this));
   syncPage = new CoreConfigWizardPages::SyncPage(this);
   setPage(AdminUserPage, new CoreConfigWizardPages::AdminUserPage(this));
   setPage(StorageSelectionPage, new CoreConfigWizardPages::StorageSelectionPage(_backends, this));
   syncPage = new CoreConfigWizardPages::SyncPage(this);
-  connect(syncPage, SIGNAL(setupCore(const QString &)), this, SLOT(prepareCoreSetup(const QString &)));
+  connect(syncPage, SIGNAL(setupCore(const QString &, const QVariantMap &)), this, SLOT(prepareCoreSetup(const QString &, const QVariantMap &)));
   setPage(SyncPage, syncPage);
   syncRelayPage = new CoreConfigWizardPages::SyncRelayPage(this);
   connect(syncRelayPage, SIGNAL(startOver()), this, SLOT(startOver()));
   setPage(SyncPage, syncPage);
   syncRelayPage = new CoreConfigWizardPages::SyncRelayPage(this);
   connect(syncRelayPage, SIGNAL(startOver()), this, SLOT(startOver()));
@@ -63,13 +65,16 @@ QHash<QString, QVariant> CoreConfigWizard::backends() const {
   return _backends;
 }
 
   return _backends;
 }
 
-void CoreConfigWizard::prepareCoreSetup(const QString &backend) {
+void CoreConfigWizard::prepareCoreSetup(const QString &backend, const QVariantMap &properties) {
   // Prevent the user from changing any settings he already specified...
   // Prevent the user from changing any settings he already specified...
-  foreach(int idx, visitedPages()) page(idx)->setEnabled(false);
+  foreach(int idx, visitedPages())
+    page(idx)->setEnabled(false);
+
   QVariantMap foo;
   foo["AdminUser"] = field("adminUser.user").toString();
   foo["AdminPasswd"] = field("adminUser.password").toString();
   foo["Backend"] = backend;
   QVariantMap foo;
   foo["AdminUser"] = field("adminUser.user").toString();
   foo["AdminPasswd"] = field("adminUser.password").toString();
   foo["Backend"] = backend;
+  foo["ConnectionProperties"] = properties;
   emit setupCore(foo);
 }
 
   emit setupCore(foo);
 }
 
@@ -91,7 +96,6 @@ void CoreConfigWizard::coreSetupFailed(const QString &error) {
   //foreach(int idx, visitedPages()) page(idx)->setEnabled(true);
   //setStartId(SyncPage);
   //restart();
   //foreach(int idx, visitedPages()) page(idx)->setEnabled(true);
   //setStartId(SyncPage);
   //restart();
-
 }
 
 void CoreConfigWizard::startOver() {
 }
 
 void CoreConfigWizard::startOver() {
@@ -183,9 +187,73 @@ QString StorageSelectionPage::selectedBackend() const {
   return ui.backendList->currentText();
 }
 
   return ui.backendList->currentText();
 }
 
+QVariantMap StorageSelectionPage::connectionProperties() const {
+  QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
+  QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap();
+  if(!properties.isEmpty() && _connectionBox) {
+    QVariantMap::iterator propertyIter = properties.begin();
+    while(propertyIter != properties.constEnd()) {
+      QWidget *widget = _connectionBox->findChild<QWidget *>(propertyIter.key());
+      switch(propertyIter.value().type()) {
+      case QVariant::Int:
+       {
+         QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
+         Q_ASSERT(spinbox);
+         propertyIter.value() = QVariant(spinbox->value());
+       }
+       break;
+      default:
+       {
+         QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
+         Q_ASSERT(lineEdit);
+         propertyIter.value() = QVariant(lineEdit->text());
+       }
+      }
+      propertyIter++;
+    }
+  }
+  return properties;
+}
+
 void StorageSelectionPage::on_backendList_currentIndexChanged() {
   QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
   ui.description->setText(_backends[backend].toMap()["Description"].toString());
 void StorageSelectionPage::on_backendList_currentIndexChanged() {
   QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
   ui.description->setText(_backends[backend].toMap()["Description"].toString());
+
+  if(_connectionBox) {
+    layout()->removeWidget(_connectionBox);
+    _connectionBox->deleteLater();
+    _connectionBox = 0;
+  }
+
+  QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap();
+  if(!properties.isEmpty()) {
+    QGroupBox *propertyBox = new QGroupBox(this);
+    propertyBox->setTitle(tr("Connection Properties"));
+    QFormLayout *formlayout = new QFormLayout;
+
+    QVariantMap::const_iterator propertyIter = properties.constBegin();
+    while(propertyIter != properties.constEnd()) {
+      QWidget *widget = 0;
+      switch(propertyIter.value().type()) {
+      case QVariant::Int:
+       {
+         QSpinBox *spinbox = new QSpinBox(propertyBox);
+         spinbox->setMaximum(64000);
+         spinbox->setValue(propertyIter.value().toInt());
+         widget = spinbox;
+       }
+       break;
+      default:
+       widget = new QLineEdit(propertyIter.value().toString(), propertyBox);
+      }
+      widget->setObjectName(propertyIter.key());
+      formlayout->addRow(propertyIter.key() + ":", widget);
+      propertyIter++;
+    }
+    propertyBox->setLayout(formlayout);
+    static_cast<QVBoxLayout *>(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, propertyBox);
+    _connectionBox = propertyBox;
+  }
 }
 
 /*** Sync Page ***/
 }
 
 /*** Sync Page ***/
@@ -199,11 +267,14 @@ SyncPage::SyncPage(QWidget *parent) : QWizardPage(parent) {
 void SyncPage::initializePage() {
   complete = false;
   hasError = false;
 void SyncPage::initializePage() {
   complete = false;
   hasError = false;
-  QString backend = qobject_cast<StorageSelectionPage *>(wizard()->page(CoreConfigWizard::StorageSelectionPage))->selectedBackend();
+
+  StorageSelectionPage *storagePage = qobject_cast<StorageSelectionPage *>(wizard()->page(CoreConfigWizard::StorageSelectionPage));
+  QString backend = storagePage->selectedBackend();
+  QVariantMap properties = storagePage->connectionProperties();
   Q_ASSERT(!backend.isEmpty());
   ui.user->setText(wizard()->field("adminUser.user").toString());
   ui.backend->setText(backend);
   Q_ASSERT(!backend.isEmpty());
   ui.user->setText(wizard()->field("adminUser.user").toString());
   ui.backend->setText(backend);
-  emit setupCore(backend);
+  emit setupCore(backend, properties);
 }
 
 int SyncPage::nextId() const {
 }
 
 int SyncPage::nextId() const {
index 7ceae20..91b532f 100644 (file)
@@ -61,7 +61,7 @@ class CoreConfigWizard : public QWizard {
     void syncFinished();
 
   private slots:
     void syncFinished();
 
   private slots:
-    void prepareCoreSetup(const QString &backend);
+    void prepareCoreSetup(const QString &backend, const QVariantMap &connectionProperties);
     void coreSetupSuccess();
     void coreSetupFailed(const QString &);
     void startOver();
     void coreSetupSuccess();
     void coreSetupFailed(const QString &);
     void startOver();
@@ -102,10 +102,13 @@ namespace CoreConfigWizardPages {
       StorageSelectionPage(const QHash<QString, QVariant> &backends, QWidget *parent = 0);
       int nextId() const;
       QString selectedBackend() const;
       StorageSelectionPage(const QHash<QString, QVariant> &backends, QWidget *parent = 0);
       int nextId() const;
       QString selectedBackend() const;
+      QVariantMap connectionProperties() const;
+
     private slots:
       void on_backendList_currentIndexChanged();
     private:
       Ui::CoreConfigWizardStorageSelectionPage ui;
     private slots:
       void on_backendList_currentIndexChanged();
     private:
       Ui::CoreConfigWizardStorageSelectionPage ui;
+      QGroupBox *_connectionBox;
       QHash<QString, QVariant> _backends;
   };
 
       QHash<QString, QVariant> _backends;
   };
 
@@ -124,7 +127,7 @@ namespace CoreConfigWizardPages {
       void setComplete(bool);
 
     signals:
       void setComplete(bool);
 
     signals:
-      void setupCore(const QString &backend);
+      void setupCore(const QString &backend, const QVariantMap &);
 
     private:
       Ui::CoreConfigWizardSyncPage ui;
 
     private:
       Ui::CoreConfigWizardSyncPage ui;
index 261426b..75f45e9 100644 (file)
@@ -5,8 +5,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>400</width>
-    <height>161</height>
+    <width>310</width>
+    <height>168</height>
    </rect>
   </property>
   <property name="windowTitle" >
    </rect>
   </property>
   <property name="windowTitle" >
@@ -40,7 +40,7 @@
        <property name="orientation" >
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="orientation" >
         <enum>Qt::Horizontal</enum>
        </property>
-       <property name="sizeHint" >
+       <property name="sizeHint" stdset="0" >
         <size>
          <width>40</width>
          <height>20</height>
         <size>
          <width>40</width>
          <height>20</height>
     </widget>
    </item>
    <item>
     </widget>
    </item>
    <item>
-    <spacer>
+    <spacer name="verticalSpacer" >
      <property name="orientation" >
       <enum>Qt::Vertical</enum>
      </property>
      <property name="orientation" >
       <enum>Qt::Vertical</enum>
      </property>
-     <property name="sizeHint" >
+     <property name="sizeHint" stdset="0" >
       <size>
       <size>
-       <width>392</width>
-       <height>51</height>
+       <width>20</width>
+       <height>40</height>
       </size>
      </property>
     </spacer>
       </size>
      </property>
     </spacer>