├── driver ├── lib │ └── as3corelib.swc └── src │ └── org │ └── postgresql │ ├── febe │ ├── message │ │ ├── IMessage.as │ │ ├── ErrorResponse.as │ │ ├── NoticeResponse.as │ │ ├── BindComplete.as │ │ ├── CloseComplete.as │ │ ├── ParseComplete.as │ │ ├── PortalSuspended.as │ │ ├── MessageError.as │ │ ├── NoData.as │ │ ├── EmptyQueryResponse.as │ │ ├── Sync.as │ │ ├── Flush.as │ │ ├── Terminate.as │ │ ├── IBEMessage.as │ │ ├── ParameterDescription.as │ │ ├── IFEMessage.as │ │ ├── ParameterStatus.as │ │ ├── BackendKeyData.as │ │ ├── NotificationResponse.as │ │ ├── CancelRequest.as │ │ ├── ReadyForQuery.as │ │ ├── Execute.as │ │ ├── Close.as │ │ ├── Query.as │ │ ├── RowDescription.as │ │ ├── DataRow.as │ │ ├── PasswordMessage.as │ │ ├── ResponseMessageBase.as │ │ ├── AbstractMessage.as │ │ ├── Describe.as │ │ ├── Parse.as │ │ ├── StartupMessage.as │ │ ├── Bind.as │ │ ├── AuthenticationRequest.as │ │ └── CommandComplete.as │ ├── IColumnInfo.as │ ├── MessageStreamFactory.as │ ├── IFieldInfo.as │ ├── MessageEvent.as │ ├── MessageStreamErrorEvent.as │ ├── MessageStreamEvent.as │ ├── BasicFieldDescription.as │ ├── ArgumentInfo.as │ ├── FieldDescription.as │ ├── IMessageStream.as │ ├── IQueryHandler.as │ ├── IExtendedQueryHandler.as │ └── IConnectionHandler.as │ ├── InvalidStateError.as │ ├── io │ ├── IDataStreamFactory.as │ ├── ICDataOutput.as │ ├── ICDataInput.as │ ├── DataStreamErrorEvent.as │ ├── DataStreamEvent.as │ ├── SocketDataStreamFactory.as │ ├── IOUtil.as │ ├── ByteDataStream.as │ ├── SocketDataStream.as │ └── IDataStream.as │ ├── UnsupportedProtocolFeatureError.as │ ├── util │ ├── AssertionError.as │ ├── AbstractMethodError.as │ ├── DateUtil.as │ ├── assert.as │ ├── NumberUtil.as │ ├── format.as │ └── getType.as │ ├── log │ ├── TraceTarget.as │ ├── ILogTarget.as │ ├── LogLevel.as │ └── ILogger.as │ ├── ProtocolError.as │ ├── TransactionStatus.as │ ├── event │ ├── ConnectionEvent.as │ ├── NoticeEvent.as │ ├── ParameterChangeEvent.as │ ├── NotificationEvent.as │ └── ConnectionErrorEvent.as │ ├── db │ ├── QueryToken.as │ ├── IColumn.as │ ├── impl │ │ ├── Column.as │ │ ├── QueryHandlerFactory.as │ │ └── ExtendedQueryHandler.as │ ├── event │ │ ├── QueryResultEvent.as │ │ └── QueryCompletionEvent.as │ ├── IResultHandler.as │ ├── EventResultHandler.as │ └── CallbackResultHandler.as │ ├── codec │ ├── encode │ │ ├── Int4In.as │ │ ├── Int2In.as │ │ ├── TextIn.as │ │ ├── Float8In.as │ │ ├── BoolIn.as │ │ ├── AbstractIntIn.as │ │ └── TimestamptzIn.as │ ├── decode │ │ ├── TextOut.as │ │ ├── BoolOut.as │ │ ├── IntOut.as │ │ └── FloatOut.as │ ├── IPGTypeEncoder.as │ └── IPGTypeDecoder.as │ ├── EncodingFormat.as │ ├── Oid.as │ ├── NoticeFields.as │ ├── CodecError.as │ └── DateStyle.as ├── pgconsole ├── lib │ ├── as3-signals-v0.8.swc │ ├── robotlegs-framework-v1.4.0.swc │ └── signals-extension-SignalCommandMap.swc └── src │ ├── org │ └── postgresql │ │ └── pgconsole │ │ ├── model │ │ ├── activity │ │ │ ├── vo │ │ │ │ ├── ConnectionActivityVO.as │ │ │ │ ├── NoticeActivityVO.as │ │ │ │ ├── NotificationActivityVO.as │ │ │ │ ├── QueryActivityVO.as │ │ │ │ └── QueryActivityResponseVO.as │ │ │ └── ConnectionActivityModel.as │ │ └── vo │ │ │ ├── NoticeVO.as │ │ │ ├── NotificationVO.as │ │ │ ├── QueryVO.as │ │ │ ├── ConnectionAttemptVO.as │ │ │ └── QueryCompletionVO.as │ │ ├── view │ │ ├── model │ │ │ ├── QueryInputViewParameter.as │ │ │ ├── QueryResultColumn.as │ │ │ ├── QueryInputViewPresentationModel.as │ │ │ ├── QueryResultViewPresentationModel.as │ │ │ ├── MainViewPresentationModel.as │ │ │ └── ConnectionActivityViewPresentationModel.as │ │ ├── QueryResultView.mxml │ │ ├── QueryInputView.mxml │ │ ├── MainView.mxml │ │ └── ConnectionActivityView.mxml │ │ ├── signal │ │ ├── ConnectedSignal.as │ │ ├── DisconnectedSignal.as │ │ ├── ErrorSignal.as │ │ ├── ResultsSelectedSignal.as │ │ ├── ConnectionActivityChangedSignal.as │ │ ├── QuerySignal.as │ │ ├── NoticeSignal.as │ │ ├── ConnectSignal.as │ │ ├── NotificationSignal.as │ │ ├── QueryCompletionSignal.as │ │ └── SelectResultsSignal.as │ │ ├── controller │ │ ├── DisconnectCommand.as │ │ ├── ExecuteCommand.as │ │ ├── AddNoticeCommand.as │ │ ├── AddQueryCommand.as │ │ ├── ConnectCommand.as │ │ ├── AddQueryCompletionCommand.as │ │ ├── SelectResultsCommand.as │ │ └── AddNotificationCommand.as │ │ └── component │ │ ├── NotificationRenderer.mxml │ │ ├── QueryResponseRenderer.mxml │ │ ├── QueryRenderer.mxml │ │ └── NoticeRenderer.mxml │ ├── PGConsole.mxml │ └── PGConsole-app.xml ├── whitespace.sh ├── .gitignore ├── test ├── libs │ ├── flexunit-core-flex-4.1.0-beta2.18-sdk3.5.0.12683.swc │ └── flexunit-uilistener-4.1.0-beta2.18-sdk3.5.0.12683.swc ├── test-config.xml ├── bootstrap.sql └── src │ ├── org │ └── postgresql │ │ └── pegasus │ │ ├── functional │ │ ├── SimpleQuerySuite.as │ │ ├── ExtendedQuerySuite.as │ │ ├── ExtendedQueryTest.as │ │ ├── SelectTestBase.as │ │ └── ConnectedTestBase.as │ │ ├── util │ │ ├── UtilSuite.as │ │ ├── TestPgURL.as │ │ ├── TestGetType.as │ │ └── TestDateFormatter.as │ │ ├── codec │ │ ├── decode │ │ │ ├── getBytes.as │ │ │ ├── TestDecodeDate.as │ │ │ └── TestDecodeFloat.as │ │ └── CodecSuite.as │ │ └── Credentials.as │ └── PegasusTest.mxml └── LICENSE /driver/lib/as3corelib.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msakrejda/pegasus/HEAD/driver/lib/as3corelib.swc -------------------------------------------------------------------------------- /pgconsole/lib/as3-signals-v0.8.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msakrejda/pegasus/HEAD/pgconsole/lib/as3-signals-v0.8.swc -------------------------------------------------------------------------------- /whitespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | find \( -name \*.as -o -name \*.mxml \) -print0 | xargs -0 sed -i -r -e 's/\t/ /g' -e 's/\s+$//' 4 | -------------------------------------------------------------------------------- /pgconsole/lib/robotlegs-framework-v1.4.0.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msakrejda/pegasus/HEAD/pgconsole/lib/robotlegs-framework-v1.4.0.swc -------------------------------------------------------------------------------- /pgconsole/lib/signals-extension-SignalCommandMap.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msakrejda/pegasus/HEAD/pgconsole/lib/signals-extension-SignalCommandMap.swc -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.actionScriptProperties 2 | **/.flexProperties 3 | **/.flexLibProperties 4 | **/.project 5 | **/.settings/ 6 | **/bin/ 7 | **/bin-debug/ 8 | 9 | -------------------------------------------------------------------------------- /test/libs/flexunit-core-flex-4.1.0-beta2.18-sdk3.5.0.12683.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msakrejda/pegasus/HEAD/test/libs/flexunit-core-flex-4.1.0-beta2.18-sdk3.5.0.12683.swc -------------------------------------------------------------------------------- /test/libs/flexunit-uilistener-4.1.0-beta2.18-sdk3.5.0.12683.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msakrejda/pegasus/HEAD/test/libs/flexunit-uilistener-4.1.0-beta2.18-sdk3.5.0.12683.swc -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/IMessage.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | public interface IMessage { 4 | function get type():String; 5 | } 6 | } -------------------------------------------------------------------------------- /test/test-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | pegasus 4 | pegasus 5 | asdbc:postgresql://localhost/pegasus 6 | 7 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/activity/vo/ConnectionActivityVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.activity.vo { 2 | 3 | public class ConnectionActivityVO { 4 | /* marker class */ 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/model/QueryInputViewParameter.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.view.model { 2 | 3 | public class QueryInputViewParameter { 4 | public var value:Object; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/ConnectedSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.osflash.signals.Signal; 3 | 4 | public class ConnectedSignal extends Signal { 5 | /* marker signal */ 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/DisconnectedSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.osflash.signals.Signal; 3 | 4 | public class DisconnectedSignal extends Signal { 5 | /* marker signal */ 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/bootstrap.sql: -------------------------------------------------------------------------------- 1 | -- Some basic bootstrap SQL for the pegasus functional tests 2 | \set ON_ERROR_STOP 3 | 4 | drop database if exists pegasus; 5 | drop user if exists pegasus; 6 | 7 | create user pegasus with password 'pegasus'; 8 | create database pegasus with owner pegasus; -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/functional/SimpleQuerySuite.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.functional { 2 | 3 | [Suite] 4 | [RunWith("org.flexunit.runners.Suite")] 5 | public class SimpleQuerySuite { 6 | public var queryTest:SimpleQueryTest; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/functional/ExtendedQuerySuite.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.functional { 2 | 3 | [Suite] 4 | [RunWith("org.flexunit.runners.Suite")] 5 | public class ExtendedQuerySuite { 6 | public var queryTest:ExtendedQueryTest; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/ErrorSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.osflash.signals.Signal; 3 | 4 | public class ErrorSignal extends Signal { 5 | public function ErrorSignal() { 6 | super(String); 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/ErrorResponse.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.IBEMessage; 4 | 5 | public class ErrorResponse extends ResponseMessageBase implements IBEMessage { 6 | /* nothing to do here: this is essentially a marker class */ 7 | } 8 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/NoticeResponse.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.IBEMessage; 4 | 5 | public class NoticeResponse extends ResponseMessageBase implements IBEMessage { 6 | /* nothing to do here: this is essentially a marker class */ 7 | } 8 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/ResultsSelectedSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.osflash.signals.Signal; 3 | 4 | public class ResultsSelectedSignal extends Signal { 5 | public function ResultsSelectedSignal() { 6 | super(Array, Array); 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/util/UtilSuite.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.util { 2 | 3 | [Suite] 4 | [RunWith("org.flexunit.runners.Suite")] 5 | public class UtilSuite { 6 | public var dateFormatterTest:TestDateFormatter; 7 | public var pgURLTest:TestPgURL; 8 | public var getTypeTest:TestGetType; 9 | } 10 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/BindComplete.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | import org.postgresql.io.ICDataInput; 3 | 4 | public class BindComplete extends AbstractMessage implements IBEMessage { 5 | 6 | public function read(input:ICDataInput):void { 7 | /* do nothing */ 8 | } 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/CloseComplete.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataInput; 4 | 5 | public class CloseComplete extends AbstractMessage implements IBEMessage { 6 | 7 | public function read(input:ICDataInput):void { 8 | // do nothing 9 | } 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/ParseComplete.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataInput; 4 | 5 | public class ParseComplete extends AbstractMessage implements IBEMessage { 6 | 7 | public function read(input:ICDataInput):void { 8 | /* do nothing */ 9 | } 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/PortalSuspended.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataInput; 4 | 5 | public class PortalSuspended extends AbstractMessage implements IBEMessage { 6 | 7 | public function read(input:ICDataInput):void { 8 | // do nothing 9 | } 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/ConnectionActivityChangedSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.osflash.signals.Signal; 3 | 4 | public class ConnectionActivityChangedSignal extends Signal { 5 | public function ConnectionActivityChangedSignal() { 6 | super(Array); 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/QuerySignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.postgresql.pgconsole.model.vo.QueryVO; 3 | import org.osflash.signals.Signal; 4 | 5 | public class QuerySignal extends Signal { 6 | public function QuerySignal() { 7 | super(QueryVO); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/IColumnInfo.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | /** 3 | * Metadata for a query result column. 4 | */ 5 | public interface IColumnInfo extends IFieldInfo { 6 | /** 7 | * The column name of the field (either explicit alias or generated) 8 | */ 9 | function get name():String 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/NoticeSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.postgresql.pgconsole.model.vo.NoticeVO; 3 | import org.osflash.signals.Signal; 4 | 5 | public class NoticeSignal extends Signal { 6 | public function NoticeSignal() { 7 | super(NoticeVO); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/ConnectSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.postgresql.pgconsole.model.vo.ConnectionAttemptVO; 3 | import org.osflash.signals.Signal; 4 | 5 | public class ConnectSignal extends Signal { 6 | public function ConnectSignal() { 7 | super(ConnectionAttemptVO); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/codec/decode/getBytes.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.codec.decode { 2 | 3 | import org.postgresql.io.ByteDataStream; 4 | 5 | public function getBytes(str:String):ByteDataStream { 6 | var bytes:ByteDataStream = new ByteDataStream(); 7 | bytes.writeUTFBytes(str); 8 | bytes.position = 0; 9 | return bytes; 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/NotificationSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.postgresql.pgconsole.model.vo.NotificationVO; 3 | import org.osflash.signals.Signal; 4 | 5 | public class NotificationSignal extends Signal { 6 | public function NotificationSignal() { 7 | super(NotificationVO); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/vo/NoticeVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.vo { 2 | 3 | public class NoticeVO { 4 | private var _fields:Object; 5 | 6 | public function NoticeVO(fields:Object) { 7 | _fields = fields; 8 | } 9 | public function get fields():Object { 10 | return _fields; 11 | } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/QueryCompletionSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.postgresql.pgconsole.model.vo.QueryCompletionVO; 3 | import org.osflash.signals.Signal; 4 | 5 | public class QueryCompletionSignal extends Signal { 6 | public function QueryCompletionSignal() { 7 | super(QueryCompletionVO); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/codec/CodecSuite.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.codec { 2 | import org.postgresql.pegasus.codec.decode.TestDecodeDate; 3 | import org.postgresql.pegasus.codec.decode.TestDecodeFloat; 4 | 5 | [Suite] 6 | [RunWith("org.flexunit.runners.Suite")] 7 | public class CodecSuite { 8 | public var dateTest:TestDecodeDate; 9 | public var floatTest:TestDecodeFloat; 10 | } 11 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/MessageError.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.ProtocolError; 4 | import org.postgresql.util.format; 5 | 6 | public class MessageError extends ProtocolError { 7 | 8 | public function MessageError(message:String, febeMsg:IMessage) { 9 | super(format("Invalid FEBE {0} message: {1}", febeMsg.type, message)); 10 | } 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/InvalidStateError.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * Indicates that the throwing object is not in the required state 5 | * to perform the requested operation. 6 | */ 7 | public class InvalidStateError extends Error { 8 | /** 9 | * @private 10 | */ 11 | public function InvalidStateError(message:String) { 12 | super(message); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/NoData.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IBEMessage; 5 | import org.postgresql.io.ICDataInput; 6 | 7 | public class NoData extends AbstractMessage implements IBEMessage { 8 | 9 | public function read(input:ICDataInput):void { 10 | /* do nothing */ 11 | } 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/IDataStreamFactory.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | /** 4 | * Factory for creating multiple IDataStream instances. 5 | */ 6 | public interface IDataStreamFactory { 7 | /** 8 | * Create a new IDataStream according to the factory's pre-configured settings. 9 | * 10 | * @return the IDataStream created 11 | */ 12 | function create():IDataStream; 13 | } 14 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/activity/vo/NoticeActivityVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.activity.vo { 2 | 3 | public class NoticeActivityVO extends ConnectionActivityVO { 4 | private var _fields:Object; 5 | 6 | public function NoticeActivityVO(fields:Object) { 7 | _fields = fields; 8 | } 9 | 10 | public function get fields():Object { 11 | return _fields; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/EmptyQueryResponse.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IBEMessage; 5 | import org.postgresql.io.ICDataInput; 6 | 7 | public class EmptyQueryResponse extends AbstractMessage implements IBEMessage { 8 | 9 | public function read(input:ICDataInput):void { 10 | /* do nothing */ 11 | } 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/signal/SelectResultsSignal.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.signal { 2 | import org.postgresql.pgconsole.model.activity.vo.QueryActivityResponseVO; 3 | import org.postgresql.pgconsole.model.vo.QueryCompletionVO; 4 | import org.osflash.signals.Signal; 5 | 6 | public class SelectResultsSignal extends Signal { 7 | public function SelectResultsSignal() { 8 | super(QueryActivityResponseVO); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/UnsupportedProtocolFeatureError.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * Indicates a ProtocolError caused by unimplemented 5 | * functionality in the driver. 6 | */ 7 | public class UnsupportedProtocolFeatureError extends ProtocolError { 8 | 9 | /** 10 | * @private 11 | */ 12 | public function UnsupportedProtocolFeatureError(message:String="") { 13 | super(message); 14 | } 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Sync.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IFEMessage; 5 | import org.postgresql.io.ICDataOutput; 6 | 7 | public class Sync extends AbstractMessage implements IFEMessage { 8 | 9 | public function write(out:ICDataOutput):void { 10 | out.writeByte(code('S')); 11 | out.writeInt(4); 12 | } 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/util/AssertionError.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.util { 2 | 3 | /** 4 | * Indicates a violation of some expected program invariant. 5 | * 6 | * @see org.postgresql.util.assert 7 | */ 8 | public class AssertionError extends Error { 9 | 10 | /** 11 | * @private 12 | */ 13 | public function AssertionError(message:String="") { 14 | super("Assertion failure: " + message); 15 | } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Flush.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IFEMessage; 5 | import org.postgresql.io.ICDataOutput; 6 | 7 | public class Flush extends AbstractMessage implements IFEMessage { 8 | 9 | public function write(out:ICDataOutput):void { 10 | out.writeByte(code('H')); 11 | out.writeInt(4); 12 | } 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/controller/DisconnectCommand.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.controller { 2 | import org.postgresql.pgconsole.service.QueryService; 3 | import org.robotlegs.mvcs.SignalCommand; 4 | 5 | public class DisconnectCommand extends SignalCommand { 6 | 7 | [Inject] 8 | public var queryService:QueryService; 9 | 10 | override public function execute():void { 11 | queryService.disconnect(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Terminate.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IFEMessage; 5 | import org.postgresql.io.ICDataOutput; 6 | 7 | public class Terminate extends AbstractMessage implements IFEMessage { 8 | 9 | public function write(out:ICDataOutput):void { 10 | out.writeByte(code('X')); 11 | out.writeInt(4); 12 | } 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /pgconsole/src/PGConsole.mxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/IBEMessage.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataInput; 4 | 5 | /** 6 | * A message sent by the server to the client. 7 | */ 8 | public interface IBEMessage extends IMessage { 9 | /** 10 | * Read the message payload. This does not include the 11 | * one-byte message type header, nor the message length. 12 | */ 13 | function read(input:ICDataInput):void; 14 | } 15 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/log/TraceTarget.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.log { 2 | 3 | /** 4 | * An ILogTarget which prints the log messages using the 5 | * built-in trace function. 6 | * 7 | * @see trace 8 | */ 9 | public class TraceTarget extends AbstractLogTarget { 10 | /** 11 | * @inheritDoc 12 | */ 13 | protected override function doHandleMessage(msg:String):void { 14 | trace(msg); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/MessageStreamFactory.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | import org.postgresql.io.IDataStreamFactory; 4 | 5 | public class MessageStreamFactory { 6 | 7 | private var _streamFactory:IDataStreamFactory; 8 | 9 | public function MessageStreamFactory(streamFactory:IDataStreamFactory) { 10 | _streamFactory = streamFactory; 11 | } 12 | 13 | public function create():IMessageStream { 14 | return new MessageStream(_streamFactory.create()); 15 | } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/ProtocolError.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * Indicates a serious miscommunication between the driver and the PostgreSQL backend. 5 | * No sensible assumptions can be made about the state of the connection after such 6 | * an error and the connection is dropped. 7 | */ 8 | public class ProtocolError extends Error { 9 | 10 | /** 11 | * @private 12 | */ 13 | public function ProtocolError(message:String="") { 14 | super(message); 15 | } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/IFieldInfo.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | /** 4 | * Metadata for a field communicated with the backend. 5 | */ 6 | public interface IFieldInfo { 7 | 8 | /** 9 | * The encoding format of the field 10 | * @see org.postgresql.EncodingFormat 11 | */ 12 | function get format():int; 13 | 14 | /** 15 | * The oid of the PostgreSQL data type of this field 16 | * @see org.postgresql.Oid 17 | */ 18 | function get typeOid():int; 19 | } 20 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/ParameterDescription.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataInput; 4 | 5 | public class ParameterDescription extends AbstractMessage implements IBEMessage { 6 | 7 | public var types:Array; 8 | 9 | public function read(input:ICDataInput):void { 10 | types = []; 11 | var paramCount:int = input.readShort(); 12 | for (var i:int = 0; i < paramCount; i++) { 13 | types.push(input.readInt()); 14 | } 15 | } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/MessageEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | import flash.events.Event; 4 | 5 | import org.postgresql.febe.message.IMessage; 6 | 7 | public class MessageEvent extends Event { 8 | 9 | public static const RECEIVED:String = "messageReceived"; 10 | public static const SENT:String = "messageSent"; 11 | 12 | public var message:IMessage; 13 | 14 | public function MessageEvent(type:String, message:IMessage) { 15 | super(type, false, false); 16 | this.message = message; 17 | } 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/model/QueryResultColumn.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.view.model { 2 | 3 | public class QueryResultColumn { 4 | private var _label:String; 5 | private var _width:Number; 6 | 7 | public function QueryResultColumn(label:String, width:Number) { 8 | _label = label; 9 | _width = width; 10 | } 11 | 12 | public function get label():String { 13 | return _label; 14 | } 15 | 16 | public function get width():Number { 17 | return _width; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/util/AbstractMethodError.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.util { 2 | 3 | /** 4 | * Error indicating that an abstract method has been invoked without being overridden 5 | * by a subclass. ActionScript does not have true abstract classes; this is used to 6 | * emulate that behavior at runtime. 7 | */ 8 | public class AbstractMethodError extends Error { 9 | 10 | /** 11 | * @private 12 | */ 13 | public function AbstractMethodError() { 14 | super("This method must be implemented by the subclass"); 15 | } 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/IFEMessage.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataOutput; 4 | 5 | /** 6 | * A message sent by the client to the server. 7 | */ 8 | public interface IFEMessage extends IMessage { 9 | /** 10 | * Write the message to the given ICDataOutput stream. 11 | * The serialization must include the entire message 12 | * as defined in the FEBE protocol, including the 13 | * message type byte and the message length. 14 | */ 15 | function write(out:ICDataOutput):void; 16 | } 17 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/controller/ExecuteCommand.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.controller { 2 | import org.postgresql.pgconsole.service.QueryService; 3 | import org.postgresql.pgconsole.model.vo.QueryVO; 4 | import org.robotlegs.mvcs.SignalCommand; 5 | 6 | public class ExecuteCommand extends SignalCommand { 7 | [Inject] 8 | public var query:QueryVO; 9 | 10 | [Inject] 11 | public var queryService:QueryService; 12 | 13 | override public function execute():void { 14 | trace('Executing', query); 15 | queryService.execute(query); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/controller/AddNoticeCommand.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.controller { 2 | import org.postgresql.pgconsole.model.activity.ConnectionActivityModel; 3 | import org.postgresql.pgconsole.model.vo.NoticeVO; 4 | import org.robotlegs.mvcs.SignalCommand; 5 | 6 | public class AddNoticeCommand extends SignalCommand { 7 | [Inject] 8 | public var notice:NoticeVO; 9 | 10 | [Inject] 11 | public var activityModel:ConnectionActivityModel; 12 | 13 | override public function execute():void { 14 | activityModel.addNotice(notice.fields); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/controller/AddQueryCommand.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.controller { 2 | import org.postgresql.pgconsole.model.activity.ConnectionActivityModel; 3 | import org.postgresql.pgconsole.model.vo.QueryVO; 4 | import org.robotlegs.mvcs.SignalCommand; 5 | 6 | public class AddQueryCommand extends SignalCommand { 7 | 8 | [Inject] 9 | public var query:QueryVO; 10 | 11 | [Inject] 12 | public var activityModel:ConnectionActivityModel; 13 | 14 | override public function execute():void { 15 | activityModel.addQuery(query); 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/vo/NotificationVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.vo { 2 | 3 | public class NotificationVO { 4 | 5 | private var _notifierPid:int; 6 | private var _condition:String; 7 | 8 | public function NotificationVO(condition:String, notifierPid:int) { 9 | _notifierPid = notifierPid; 10 | _condition = condition; 11 | } 12 | 13 | public function get notifierPid():int { 14 | return _notifierPid; 15 | } 16 | 17 | public function get condition():String { 18 | return _condition; 19 | } 20 | 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/ParameterStatus.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataInput; 4 | import org.postgresql.util.format; 5 | 6 | public class ParameterStatus extends AbstractMessage implements IBEMessage { 7 | 8 | public var name:String; 9 | public var value:String; 10 | 11 | public function read(input:ICDataInput):void { 12 | name = input.readCString(); 13 | value = input.readCString(); 14 | } 15 | 16 | public override function toString():String { 17 | return format("{0} {{1}: {2}}", type, name, value); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/controller/ConnectCommand.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.controller { 2 | import org.postgresql.pgconsole.service.QueryService; 3 | import org.postgresql.pgconsole.model.vo.ConnectionAttemptVO; 4 | import org.robotlegs.mvcs.SignalCommand; 5 | 6 | public class ConnectCommand extends SignalCommand { 7 | 8 | [Inject] 9 | public var parameters:ConnectionAttemptVO; 10 | [Inject] 11 | public var queryService:QueryService; 12 | 13 | override public function execute():void { 14 | queryService.connect(parameters.url, parameters.username, parameters.password); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/ICDataOutput.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | import flash.utils.IDataOutput; 4 | /** 5 | * An IDataInput that can also write null-terminated character strings from ActionScript Strings 6 | * 7 | * @see flash.utils.IDataOutput 8 | */ 9 | public interface ICDataOutput extends IDataOutput { 10 | /** 11 | * Write a C-style, NULL-terminated String to the stream. This will write 12 | * the bytes of the given String followed by the byte 0x00. 13 | * 14 | * @param str String to write out 15 | */ 16 | function writeCString(str:String):void; 17 | } 18 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/activity/vo/NotificationActivityVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.activity.vo { 2 | 3 | public class NotificationActivityVO extends ConnectionActivityVO { 4 | 5 | private var _notifierPid:int; 6 | private var _condition:String; 7 | 8 | public function NotificationActivityVO(condition:String, pid:int) { 9 | _condition = condition; 10 | _notifierPid = pid; 11 | } 12 | 13 | public function get condition():String { 14 | return _condition; 15 | } 16 | 17 | public function get notifierPid():int { 18 | return _notifierPid; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/vo/QueryVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.vo { 2 | 3 | public class QueryVO { 4 | private var _sql:String; 5 | private var _args:Array; 6 | 7 | public function QueryVO(sql:String, args:Array) { 8 | _sql = sql; 9 | _args = args; 10 | } 11 | 12 | public function get sql():String { 13 | return _sql; 14 | } 15 | 16 | public function get args():Array { 17 | return _args; 18 | } 19 | 20 | public function toString():String { 21 | return 'sql: {' + _sql + '} args {' + (args ? args.join(', ') : '') + '}'; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/TransactionStatus.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * Possible values for the current transaction status of the connection. 5 | */ 6 | public class TransactionStatus { 7 | /** 8 | * The connection is not in an open transaction. 9 | */ 10 | public static const IDLE:String = 'I'; 11 | /** 12 | * The connection is in an open transaction. 13 | */ 14 | public static const IN_TRANSACTION_BLOCK:String = 'T'; 15 | /** 16 | * The connection is in a failed transaction. The transaction 17 | * must be rolled back. 18 | */ 19 | public static const IN_TRANSACTION_ERROR:String = 'E'; 20 | } 21 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/BackendKeyData.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IBEMessage; 5 | import org.postgresql.io.ICDataInput; 6 | 7 | public class BackendKeyData extends AbstractMessage implements IBEMessage { 8 | 9 | public var pid:int; 10 | public var key:int; 11 | 12 | public function read(input:ICDataInput):void { 13 | pid = input.readInt(); 14 | key = input.readInt(); 15 | } 16 | 17 | public override function toString():String { 18 | return super.toString() + ' {pid:' + pid + ',key:' + key + '}'; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/ICDataInput.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | import flash.utils.IDataInput; 4 | /** 5 | * An IDataInput that can also read null-terminated character strings. 6 | * 7 | * @see flash.utils.IDataInput 8 | */ 9 | public interface ICDataInput extends IDataInput { 10 | /** 11 | * Reads a C-style, NULL-terminated String from the stream. 12 | *
13 | * Consumes input until it finds the NULL byte 0x00--everything 14 | * up to (but not including) this byte is considered part of the String. 15 | * 16 | * @return the decoded String 17 | */ 18 | function readCString():String; 19 | } 20 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/event/ConnectionEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.event { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * Indicates a change to the state of the connection. 7 | */ 8 | public class ConnectionEvent extends Event { 9 | 10 | /** 11 | * A connection to the backend has been established. 12 | * 13 | * @eventType connected 14 | */ 15 | public static const CONNECTED:String = 'connected'; 16 | 17 | /** 18 | * Create a new connetion event 19 | * 20 | * @param type event type 21 | * 22 | * @private 23 | */ 24 | public function ConnectionEvent(type:String) { 25 | super(type); 26 | } 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/controller/AddQueryCompletionCommand.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.controller { 2 | import org.postgresql.pgconsole.model.activity.ConnectionActivityModel; 3 | import org.postgresql.pgconsole.model.vo.QueryCompletionVO; 4 | import org.robotlegs.mvcs.SignalCommand; 5 | 6 | public class AddQueryCompletionCommand extends SignalCommand { 7 | 8 | [Inject] 9 | public var completion:QueryCompletionVO; 10 | 11 | [Inject] 12 | public var activityModel:ConnectionActivityModel; 13 | 14 | override public function execute():void { 15 | activityModel.addQueryCompletion(completion.command, completion.affectedRows, completion.columns, completion.data); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/MessageStreamErrorEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | import flash.events.ErrorEvent; 4 | 5 | /** 6 | * An Event describing an error in an IMessageBroker. 7 | * 8 | * @see org.postgresql.io.IDataStream 9 | */ 10 | public class MessageStreamErrorEvent extends ErrorEvent { 11 | 12 | /** 13 | * An error has occurred in reading from the message stream. The message stream itself 14 | * may still be in a valid state. 15 | * 16 | * @eventType error 17 | */ 18 | public static const ERROR:String = 'error'; 19 | 20 | public function MessageStreamErrorEvent(type:String, text:String="") { 21 | super(type, false, false, text); 22 | } 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/util/DateUtil.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.util { 2 | 3 | /** 4 | * Utility functions and useful constants related to dates 5 | */ 6 | public class DateUtil { 7 | /** 8 | * The "ticks" (milliseconds since 1970) corresponding to the largest (i.e., furthest in 9 | * the future) Date instance representable in ActionScript, as per the ECMAScript spec. 10 | */ 11 | public static const MAX_DATE_TICKS:Number = 8640000000000000; 12 | /** 13 | * The "ticks" (milliseconds since 1970) corresponding to the smallest (i.e., furthest in 14 | * the past) Date instance representable in ActionScript, as per the ECMAScript spec. 15 | */ 16 | public static const MIN_DATE_TICKS:Number = -8640000000000000; 17 | } 18 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/controller/SelectResultsCommand.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.controller { 2 | import org.postgresql.pgconsole.model.activity.ConnectionActivityModel; 3 | import org.postgresql.pgconsole.model.activity.vo.QueryActivityResponseVO; 4 | import org.robotlegs.mvcs.SignalCommand; 5 | 6 | public class SelectResultsCommand extends SignalCommand { 7 | 8 | [Inject] 9 | public var queryResponse:QueryActivityResponseVO; 10 | 11 | [Inject] 12 | public var model:ConnectionActivityModel; 13 | 14 | override public function execute():void { 15 | if (queryResponse.columns && queryResponse.data) { 16 | model.selectQueryResult(queryResponse.columns, queryResponse.data); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/NotificationResponse.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataInput; 4 | 5 | public class NotificationResponse extends AbstractMessage implements IBEMessage { 6 | 7 | public var notifierPid:int; 8 | public var condition:String; 9 | public var auxinfo:String; 10 | 11 | public function read(input:ICDataInput):void { 12 | notifierPid = input.readInt(); 13 | condition = input.readCString(); 14 | auxinfo = input.readCString(); 15 | } 16 | 17 | public override function toString():String { 18 | return super.toString() + '{' + condition + ' from pid ' + notifierPid + 19 | (auxinfo.length > 0 ? '(' + auxinfo + ')' : '') + '}'; 20 | } 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/vo/ConnectionAttemptVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.vo { 2 | 3 | public class ConnectionAttemptVO { 4 | 5 | private var _url:String; 6 | private var _username:String; 7 | private var _password:String; 8 | 9 | public function ConnectionAttemptVO(url:String, username:String, password:String):void { 10 | _url = url; 11 | _username = username; 12 | _password = password; 13 | } 14 | 15 | public function get url():String { 16 | return _url; 17 | } 18 | 19 | public function get username():String { 20 | return _username; 21 | } 22 | 23 | public function get password():String { 24 | return _password; 25 | } 26 | 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/QueryToken.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db { 2 | 3 | /** 4 | * Class to identify a particular query execution. 5 | *
6 | * Note that while this can be managed through the query SQL in many situations, that 7 | * approach fails when the same query is submitted concurrently several times. Currently, 8 | * QueryTokens are only used to cancel queries. 9 | */ 10 | public class QueryToken { 11 | 12 | private var _sql:String; 13 | 14 | /** 15 | * @private 16 | */ 17 | public function QueryToken(sql:String) { 18 | _sql = sql; 19 | } 20 | 21 | /** 22 | * The SQL of the associated query 23 | */ 24 | public function get sql():String { 25 | return _sql; 26 | } 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/CancelRequest.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IFEMessage; 5 | import org.postgresql.io.ICDataOutput; 6 | 7 | public class CancelRequest extends AbstractMessage implements IFEMessage { 8 | 9 | private static const CANCEL_CODE:int = 80877102; 10 | 11 | private var _pid:int; 12 | private var _key:int; 13 | 14 | public function CancelRequest(pid:int, key:int) { 15 | _pid = pid; 16 | _key = key; 17 | } 18 | 19 | public function write(out:ICDataOutput):void { 20 | out.writeInt(16); 21 | out.writeInt(CANCEL_CODE); 22 | out.writeInt(_pid); 23 | out.writeInt(_key); 24 | } 25 | 26 | } 27 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/controller/AddNotificationCommand.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.controller { 2 | import org.postgresql.pgconsole.model.vo.NotificationVO; 3 | import org.postgresql.pgconsole.model.activity.vo.NotificationActivityVO; 4 | import org.postgresql.pgconsole.model.activity.ConnectionActivityModel; 5 | import org.postgresql.pgconsole.model.vo.NoticeVO; 6 | import org.robotlegs.mvcs.SignalCommand; 7 | 8 | public class AddNotificationCommand extends SignalCommand { 9 | [Inject] 10 | public var notification:NotificationVO; 11 | 12 | [Inject] 13 | public var activityModel:ConnectionActivityModel; 14 | 15 | override public function execute():void { 16 | activityModel.addNotification(notification.condition, notification.notifierPid); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/IColumn.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db { 2 | /** 3 | * Describes a field of data in a query result. 4 | */ 5 | public interface IColumn { 6 | /** 7 | * The name of this column: either the alias specified in the target 8 | * list of the query, or the name generated by PostgreSQL if no 9 | * alias was used. 10 | */ 11 | function get name():String; 12 | /** 13 | * The client-side data type of the column. This is determined by the 14 | * oid of the column's (server-side) data type and the decoder registered 15 | * for that data type in the current configuration. 16 | */ 17 | function get type():Class; 18 | /** 19 | * The oid of the column's actual, server-side data type. 20 | */ 21 | function get typeOid():int; 22 | } 23 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/encode/Int4In.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.encode { 2 | 3 | import org.postgresql.Oid; 4 | import org.postgresql.io.ICDataOutput; 5 | 6 | /** 7 | * Encodes ActionScript ints into PostgreSQL int4 values. 8 | */ 9 | public class Int4In extends AbstractIntIn { 10 | 11 | /** 12 | * Encodes a 2-byte integer in binary mode. 13 | */ 14 | protected override function binaryEncodeInt(bytes:ICDataOutput, value:Object, serverParams:Object):void { 15 | bytes.writeInt(int(value)); 16 | } 17 | 18 | /** 19 | * This encoder returns Oid.INT4. 20 | * 21 | * @see org.postgresql.Oid#INT4 22 | */ 23 | public override function getInputOid(clazz:Class):int { 24 | return Oid.INT4; 25 | } 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/encode/Int2In.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.encode { 2 | import org.postgresql.io.ICDataOutput; 3 | import org.postgresql.Oid; 4 | 5 | /** 6 | * Encodes ActionScript ints into PostgreSQL int2 values. 7 | */ 8 | public class Int2In extends AbstractIntIn { 9 | 10 | /** 11 | * Encodes a 2-byte integer in binary mode. 12 | */ 13 | protected override function binaryEncodeInt(bytes:ICDataOutput, value:Object, serverParams:Object):void { 14 | bytes.writeShort(int(value)); 15 | } 16 | 17 | /** 18 | * This encoder returns Oid.INT2. 19 | * 20 | * @see org.postgresql.Oid#INT2 21 | */ 22 | public override function getInputOid(clazz:Class):int { 23 | return Oid.INT2; 24 | } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/ReadyForQuery.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.TransactionStatus; 4 | import org.postgresql.io.ICDataInput; 5 | 6 | public class ReadyForQuery extends AbstractMessage implements IBEMessage { 7 | 8 | public var status:String; 9 | 10 | public function read(input:ICDataInput):void { 11 | status = String.fromCharCode(input.readByte()); 12 | if (status != TransactionStatus.IDLE && 13 | status != TransactionStatus.IN_TRANSACTION_BLOCK && 14 | status != TransactionStatus.IN_TRANSACTION_ERROR) { 15 | throw new MessageError("Invalid status in ReadyForQuery", this); 16 | } 17 | } 18 | 19 | public override function toString():String { 20 | return type + " {" + status + "}"; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/activity/vo/QueryActivityVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.activity.vo { 2 | import mx.collections.ArrayCollection; 3 | 4 | public class QueryActivityVO extends ConnectionActivityVO { 5 | 6 | private var _sql:String; 7 | private var _args:Array; 8 | private var _responses:ArrayCollection; 9 | 10 | public function QueryActivityVO(sql:String, args:Array, responses:Array) { 11 | _sql = sql; 12 | _args = args; 13 | _responses = new ArrayCollection(responses); 14 | } 15 | 16 | public function get sql():String { 17 | return _sql; 18 | } 19 | 20 | public function get args():Array { 21 | return _args; 22 | } 23 | 24 | public function get responses():ArrayCollection { 25 | return _responses; 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/util/assert.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.util { 2 | 3 | /** 4 | * Assert an expected program invariant by verifying that the given expression 5 | * evaluates to true. Throw an AssertionError with the given message if the assertion 6 | * fails. Note that assert is a regular function, so the expression is evaluated 7 | * before being passed to assert. Most notably, this means that the 8 | * expression itself cannot be printed (unless it's duplicated in the message), 9 | * and it will be evaluated even when running in release mode. 10 | * 11 | * @param msg failure message 12 | * @param expression expression to evaluate 13 | * @see org.postgresql.util.AssertionError 14 | */ 15 | public function assert(msg:String, expression:*=false):void { 16 | if (!expression) { 17 | throw new AssertionError(msg); 18 | } 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Execute.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataOutput; 4 | 5 | public class Execute extends AbstractMessage implements IFEMessage { 6 | 7 | public var portal:String; 8 | public var limit:int; 9 | 10 | public function Execute(portal:String, limit:int) { 11 | this.portal = portal; 12 | this.limit = limit; 13 | } 14 | 15 | public function write(out:ICDataOutput):void { 16 | out.writeByte(code('E')); 17 | var len:int = 4 + portal.length + 1 + 4; 18 | out.writeInt(len); 19 | out.writeCString(portal); 20 | out.writeInt(limit); 21 | } 22 | 23 | public override function toString():String { 24 | return super.toString() + ' {' + portal + (limit > 0 ? ' (fetch' + limit + ')' : '') + '}'; 25 | } 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/MessageStreamEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * An Event describing normal activity from a MessageBroker. 7 | * 8 | * @see org.postgresql.febe.MessageStream 9 | */ 10 | public class MessageStreamEvent extends Event { 11 | 12 | /** 13 | * Incoming messages on a MessageStream may arrive in batches. When a 14 | * batch of messages has been processed, this event is dispatched. It allows for 15 | * processing of a set of messages and once and enables features like result set 16 | * streaming. 17 | * 18 | * @eventType batchComplete 19 | */ 20 | public static const BATCH_COMPLETE:String = 'batchComplete'; 21 | 22 | public function MessageStreamEvent(type:String) { 23 | super(type); 24 | } 25 | 26 | } 27 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/DataStreamErrorEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | import flash.events.ErrorEvent; 4 | 5 | /** 6 | * An Event describing an error in an IDataStream. 7 | * 8 | * @see org.postgresql.io.IDataStream 9 | */ 10 | public class DataStreamErrorEvent extends ErrorEvent { 11 | 12 | /** 13 | * An error in the stream. The text specified contains more details. 14 | * 15 | * @eventType dataStreamError 16 | */ 17 | public static const ERROR:String = 'dataStreamError'; 18 | 19 | /** 20 | * Create a new event of given type 21 | * 22 | * @param type event type 23 | * @param text error text 24 | * 25 | * @private 26 | */ 27 | public function DataStreamErrorEvent(type:String, text:String = "") { 28 | super(type, false, false, text); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/functional/ExtendedQueryTest.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.functional { 2 | 3 | import org.postgresql.db.IColumn; 4 | import org.postgresql.db.event.QueryResultEvent; 5 | import org.flexunit.asserts.assertEquals; 6 | 7 | public class ExtendedQueryTest extends SelectTestBase { 8 | 9 | [Test(async,timeout=5000)] 10 | public function testSelectInt():void { 11 | // TODO: this should handle smallint as well 12 | var verifyFn:Function = function(e:QueryResultEvent) : void { 13 | assertEquals(1, e.columns.length); 14 | assertEquals('arg', IColumn(e.columns[0]).name); 15 | 16 | assertEquals(1, e.data.length); 17 | assertEquals(0, e.data[0]['arg']); 18 | }; 19 | 20 | var sql:String = "select $1::int as arg"; 21 | runQuery(verifyFn, sql, [ 0 ]); 22 | } 23 | 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/DataStreamEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * An Event describing normal activity on a IDataStream. 7 | * 8 | * @see org.postgresql.io.IDataStream 9 | */ 10 | public class DataStreamEvent extends Event { 11 | 12 | /** 13 | * New data is available to be read from this IDataStream. 14 | * Inspect the dispatching stream itself (i.e., the target) 15 | * to find the incoming data. 16 | * 17 | * @eventType progress 18 | */ 19 | public static const PROGRESS:String = 'progress'; 20 | 21 | /** 22 | * Create a new DataStreamEvent of given type 23 | * @param type event type 24 | * 25 | * @private 26 | */ 27 | public function DataStreamEvent(type:String) { 28 | super(type); 29 | } 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/SocketDataStreamFactory.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | /** 4 | * Factory class to create SocketDataStreams to a given 5 | * host and port. 6 | * 7 | * @see SocketDataStream 8 | */ 9 | public class SocketDataStreamFactory implements IDataStreamFactory { 10 | 11 | private var _host:String; 12 | private var _port:int; 13 | 14 | /** 15 | * Create a new factory for connections to given host and port 16 | * 17 | * @param host host to connect to 18 | * @param port port to connect to 19 | */ 20 | public function SocketDataStreamFactory(host:String, port:int) { 21 | _host = host; 22 | _port = port; 23 | } 24 | 25 | /** 26 | * @inheritDoc 27 | */ 28 | public function create():IDataStream { 29 | return new SocketDataStream(_host, _port); 30 | } 31 | 32 | } 33 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Close.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataOutput; 4 | 5 | public class Close extends AbstractMessage implements IFEMessage { 6 | 7 | public static const PORTAL:String = 'P'; 8 | public static const STATEMENT:String = 'S'; 9 | 10 | public var kind:String; 11 | public var name:String; 12 | 13 | public function Close(kind:String, name:String) { 14 | if (kind != PORTAL && kind != STATEMENT) { 15 | throw new ArgumentError("Unknown close kind for " + name + ": " + kind); 16 | } 17 | this.kind = kind; 18 | this.name = name; 19 | } 20 | 21 | public function write(out:ICDataOutput):void { 22 | out.writeByte(code('C')); 23 | out.writeInt(4 + 1 + name.length + 1); 24 | out.writeByte(code(kind)); 25 | out.writeCString(name); 26 | } 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Query.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IFEMessage; 5 | import org.postgresql.io.ICDataOutput; 6 | 7 | public class Query extends AbstractMessage implements IFEMessage { 8 | 9 | public var query:String; 10 | 11 | public function Query(query:String) { 12 | if (query == null) { 13 | throw new ArgumentError("query must not be null"); 14 | } 15 | this.query = query; 16 | } 17 | 18 | public function write(out:ICDataOutput):void { 19 | out.writeByte(code('Q')); 20 | var len:int = 4 + query.length + 1; 21 | out.writeInt(len); 22 | out.writeCString(query); 23 | } 24 | 25 | public override function toString():String { 26 | return super.toString() + ' {' + query + '}'; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/BasicFieldDescription.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | /** 4 | * Basic IFieldInfo implementation, largely for testing. 5 | */ 6 | public class BasicFieldDescription implements IFieldInfo { 7 | 8 | private var _typeOid:int; 9 | private var _format:int; 10 | 11 | /** 12 | * Constructor 13 | * 14 | * @param format format of this parameter 15 | * @param oid server-side type of this parameter 16 | * 17 | * @private 18 | */ 19 | public function BasicFieldDescription(oid:int, format:int) { 20 | _typeOid = oid; 21 | _format = format; 22 | } 23 | 24 | /** 25 | * @inheritDoc 26 | */ 27 | public function get format():int { return _format; } 28 | 29 | /** 30 | * @inheritDoc 31 | */ 32 | public function get typeOid():int { return _typeOid; } 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/activity/vo/QueryActivityResponseVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.activity.vo { 2 | 3 | public class QueryActivityResponseVO extends ConnectionActivityVO { 4 | 5 | private var _tag:String; 6 | private var _rows:int; 7 | private var _columns:Array; 8 | private var _data:Array; 9 | 10 | public function QueryActivityResponseVO(tag:String, rows:int, columns:Array=null, data:Array=null) { 11 | _rows = rows; 12 | _tag = tag; 13 | _data = data; 14 | _columns = columns; 15 | } 16 | 17 | public function get data():Array { 18 | return _data; 19 | } 20 | 21 | public function get columns():Array { 22 | return _columns; 23 | } 24 | 25 | public function get tag():String { 26 | return _tag; 27 | } 28 | 29 | public function get rows():int { 30 | return _rows; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/RowDescription.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.FieldDescription; 4 | import org.postgresql.io.ICDataInput; 5 | 6 | public class RowDescription extends AbstractMessage implements IBEMessage { 7 | 8 | public var fields:Array; 9 | 10 | public function read(input:ICDataInput):void { 11 | fields = []; 12 | var numFields:int = input.readShort(); 13 | for (var i:int = 0; i < numFields; i++) { 14 | var field:FieldDescription = new FieldDescription(); 15 | try { 16 | field.read(input); 17 | } catch (e:ArgumentError) { 18 | throw new MessageError(e.message, this); 19 | } 20 | fields.push(field); 21 | } 22 | } 23 | 24 | public override function toString():String { 25 | return super.toString() + ' {' + fields.join(', ') + '}'; 26 | } 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/vo/QueryCompletionVO.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.vo { 2 | 3 | public class QueryCompletionVO { 4 | 5 | private var _command:String; 6 | private var _affectedRows:int; 7 | private var _columns:Array; 8 | private var _data:Array; 9 | 10 | public function QueryCompletionVO(command:String, affectedRows:int, columns:Array=null, data:Array=null) { 11 | _affectedRows = affectedRows; 12 | _command = command; 13 | _columns = columns; 14 | _data = data; 15 | } 16 | 17 | public function get command():String { 18 | return _command; 19 | } 20 | 21 | public function get affectedRows():int { 22 | return _affectedRows; 23 | } 24 | 25 | public function get data():Array { 26 | return _data; 27 | } 28 | 29 | public function get columns():Array { 30 | return _columns; 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/DataRow.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ByteDataStream; 4 | import org.postgresql.io.ICDataInput; 5 | 6 | public class DataRow extends AbstractMessage implements IBEMessage { 7 | 8 | public var rowBytes:Array; 9 | 10 | public function read(input:ICDataInput):void { 11 | rowBytes = []; 12 | var colCount:int = input.readShort(); 13 | for (var i:int = 0; i < colCount; i++) { 14 | var fieldByteCount:int = input.readInt(); 15 | var fieldBytes:ByteDataStream; 16 | if (fieldByteCount >= 0) { 17 | fieldBytes = new ByteDataStream(); 18 | if (fieldByteCount > 0) { 19 | input.readBytes(fieldBytes, 0, fieldByteCount); 20 | } 21 | } else { 22 | fieldBytes = null; 23 | } 24 | rowBytes.push(fieldBytes); 25 | } 26 | } 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/PasswordMessage.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IFEMessage; 5 | import org.postgresql.io.ICDataOutput; 6 | 7 | public class PasswordMessage extends AbstractMessage implements IFEMessage { 8 | private var _password:String; 9 | 10 | public function PasswordMessage(password:String) { 11 | _password = password; 12 | } 13 | 14 | public function write(out:ICDataOutput):void { 15 | out.writeByte(code('p')); 16 | var len:int = 4 + _password.length + 1; 17 | out.writeInt(len); 18 | // Note that for GSSAPI and SSPI, this will not be correct, even though 19 | // they nominally use the same message type. We may want to add a 20 | // GSSPasswordMessage pseudo-message to handle that when adding these 21 | // authentication protocols. 22 | out.writeCString(_password); 23 | } 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/util/NumberUtil.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.util { 2 | 3 | /** 4 | * Utility functions and useful constants related to floating point numbers 5 | */ 6 | public class NumberUtil { 7 | /** 8 | * The largest value representable in an IEEE-754 32-bit floating point number. 9 | */ 10 | public static const FLOAT_MAX_VALUE:Number = 3.4028234663852886e+38; 11 | /** 12 | * The smallest value representable in a denormalized IEEE-754 32-bit floating point number. 13 | */ 14 | public static const FLOAT_MIN_VALUE:Number = 1.401298464324817e-45; 15 | /** 16 | * The smallest value representable in a normalized IEEE 32-bit floating point number. 17 | */ 18 | public static const FLOAT_MIN_NORMAL:Number = 1.1754943508222875e-38; 19 | /** 20 | * The smallest value representable in a normalized IEEE 64-bit floating point number. 21 | */ 22 | public static const DOUBLE_MIN_NORMAL:Number = 2.2250738585072014e-308; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/model/QueryInputViewPresentationModel.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.view.model { 2 | import mx.collections.ArrayCollection; 3 | import org.postgresql.pgconsole.model.vo.QueryVO; 4 | import org.postgresql.pgconsole.signal.QuerySignal; 5 | 6 | public class QueryInputViewPresentationModel { 7 | [Inject] 8 | public var query:QuerySignal; 9 | 10 | public var args:ArrayCollection; 11 | 12 | public function QueryInputViewPresentationModel() { 13 | args = new ArrayCollection(); 14 | } 15 | 16 | public function execute(sql:String):void { 17 | var queryArgs:Array; 18 | if (args.length > 0) { 19 | queryArgs = []; 20 | for each (var item:QueryInputViewParameter in args) { 21 | queryArgs.push(item.value); 22 | } 23 | } else { 24 | queryArgs = null; 25 | } 26 | query.dispatch(new QueryVO(sql, queryArgs)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/model/QueryResultViewPresentationModel.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.view.model { 2 | import org.postgresql.db.IColumn; 3 | import mx.collections.ArrayCollection; 4 | import org.postgresql.pgconsole.signal.ResultsSelectedSignal; 5 | 6 | public class QueryResultViewPresentationModel { 7 | [Inject] 8 | public var resultsSelected:ResultsSelectedSignal; 9 | 10 | [PostConstruct] 11 | public function initialize():void { 12 | resultsSelected.add(onResultsSelected); 13 | } 14 | 15 | private function onResultsSelected(columns:Array, data:Array):void { 16 | var newCols:Array = columns.map(function(col:IColumn, index:int, array:Array):String { 17 | return col.name; 18 | }); 19 | columnNames = newCols; 20 | dataProvider = new ArrayCollection(data); 21 | } 22 | 23 | [Bindable] 24 | public var columnNames:Array; 25 | 26 | [Bindable] 27 | public var dataProvider:ArrayCollection; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/impl/Column.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db.impl { 2 | import org.postgresql.db.IColumn; 3 | /** 4 | * Basic IColumn implementation. 5 | */ 6 | internal class Column implements IColumn { 7 | private var _name:String; 8 | private var _type:Class; 9 | private var _typeOid:int; 10 | 11 | /** 12 | * @private 13 | */ 14 | public function Column(name:String, type:Class, typeOid:int) { 15 | _name = name; 16 | _type = type; 17 | _typeOid = typeOid; 18 | } 19 | 20 | /** 21 | * Column name. 22 | */ 23 | public function get name():String { return _name; } 24 | 25 | /** 26 | * Column client-side type (i.e., actual ActionScript Class this data has been decoded to). 27 | */ 28 | public function get type():Class { return _type; } 29 | 30 | /** 31 | * Column server-side type (i.e., original oid of result column in PostgreSQL). 32 | */ 33 | public function get typeOid():int { return _typeOid; } 34 | } 35 | } -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/Credentials.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus { 2 | import flash.utils.ByteArray; 3 | /** 4 | * Credentials used for testing. 5 | */ 6 | public class Credentials { 7 | 8 | [Embed(source="../test-config.xml", mimeType="application/octet-stream")] 9 | private static const ConfigXML:Class; 10 | private static var _config:XML; 11 | 12 | private static function get config():XML { 13 | // TODO: this should be possible in a static initializer block, but I'm getting 14 | // odd errors about undefined properties when I try to do that 15 | if (!_config) { 16 | var ba:ByteArray = (new ConfigXML()) as ByteArray; 17 | var str:String = ba.readUTFBytes(ba.length); 18 | _config = new XML(str); 19 | } 20 | return _config; 21 | } 22 | 23 | public static function get user():String { return config.user; } 24 | public static function get password():String { return config.password; } 25 | public static function get url():String { return config.url; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/EncodingFormat.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * Functionality defining encodings of data in the protocol. 5 | */ 6 | public class EncodingFormat { 7 | /** 8 | * The PostgreSQL text format. This is essentially equivalent to how datatypes 9 | * are presented through psql. 10 | */ 11 | public static const TEXT:int = 0; 12 | /** 13 | * The PostgreSQL binary format. This is a custom binary format. 14 | */ 15 | public static const BINARY:int = 1; 16 | /** 17 | * Utility function to validate the given format. Does nothing if the format 18 | * is valid; throws an ArgumentError otherwise. 19 | * 20 | * @param format format to validate 21 | * @throws ArgumentError if format is not recognized 22 | * @see #TEXT 23 | * @see #BINARY 24 | */ 25 | public static function validate(format:int):void { 26 | if (format != TEXT && format != BINARY) { 27 | throw new ArgumentError("Unrecognized encoding format: " + format); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/ResponseMessageBase.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.NoticeFields; 4 | import org.postgresql.febe.message.AbstractMessage; 5 | import org.postgresql.febe.message.IBEMessage; 6 | import org.postgresql.io.ICDataInput; 7 | 8 | public /* abstract */ class ResponseMessageBase extends AbstractMessage implements IBEMessage { 9 | 10 | public var fields:Object; 11 | 12 | public function read(input:ICDataInput):void { 13 | fields = {}; 14 | var nextByte:int; 15 | while ((nextByte = input.readByte()) != 0) { 16 | var fieldType:String = String.fromCharCode(nextByte); 17 | fields[fieldType] = input.readCString(); 18 | } 19 | } 20 | 21 | public override function toString():String { 22 | var items:Array = []; 23 | for (var key:String in fields) { 24 | var keyDescription:String = NoticeFields.describe(key) || ('UNKNOWN FIELD(' + key + ')'); 25 | items.push(keyDescription + ': ' + fields[key]); 26 | } 27 | return super.toString() + '[' + items.join(', ') + ']'; 28 | } 29 | 30 | } 31 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/AbstractMessage.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | public class AbstractMessage implements IMessage { 4 | 5 | /** 6 | * This returns the unqualified class name; we 7 | * name our messages using FEBE message names, 8 | * so this corresponds to the official messages names 9 | */ 10 | public function get type():String { 11 | var classStr:String = String(Object(this).constructor); 12 | return classStr.replace(/\[class (\w+)\]/, '$1'); 13 | } 14 | 15 | /** 16 | * Print the message type. 17 | * 18 | * @see #type 19 | */ 20 | public function toString():String { 21 | return type; 22 | } 23 | 24 | /** 25 | * Get character code of first character in given String. 26 | * 27 | * @param str String, must be a single character 28 | */ 29 | protected function code(str:String):int { 30 | if (str.length > 1) { 31 | throw new ArgumentError("Expected single character, got " + str); 32 | } else { 33 | return str.charCodeAt(0); 34 | } 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Describe.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IFEMessage; 5 | import org.postgresql.febe.message.MessageError; 6 | import org.postgresql.io.ICDataOutput; 7 | 8 | public class Describe extends AbstractMessage implements IFEMessage { 9 | 10 | public static const PORTAL:String = 'P'; 11 | public static const STATEMENT:String = 'S'; 12 | 13 | private var _name:String; 14 | private var _type:String; 15 | 16 | public function Describe(name:String, type:String) { 17 | _name = name; 18 | if (type != PORTAL && type != STATEMENT) { 19 | throw new MessageError("unknown describe type: " + type, this); 20 | } 21 | _type = type; 22 | } 23 | 24 | public function write(out:ICDataOutput):void { 25 | out.writeByte(code('D')); 26 | var len:int = 4 + 1 + _name.length + 1; 27 | out.writeInt(len); 28 | out.writeByte(code(_type)); 29 | out.writeCString(_name); 30 | } 31 | 32 | public override function toString():String { 33 | return super.toString() + ' {' + _type + ' ' + _name + '}'; 34 | } 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/component/NotificationRenderer.mxml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/ArgumentInfo.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | import flash.utils.ByteArray; 3 | 4 | /** 5 | * Describes a parameter and how it will be passed to the PostgreSQL backend. 6 | */ 7 | public class ArgumentInfo implements IFieldInfo { 8 | private var _format:int; 9 | private var _value:ByteArray; 10 | private var _oid:int; 11 | 12 | /** 13 | * @private 14 | */ 15 | public function ArgumentInfo(format:int, oid:int, value:ByteArray) { 16 | _format = format; 17 | _oid = oid; 18 | _value = value; 19 | } 20 | 21 | /** 22 | * The encoding format of this parameter. 23 | * @see org.postgresql.EncodingFormat 24 | */ 25 | public function get format():int { 26 | return _format; 27 | } 28 | 29 | /** 30 | * The PostgreSQL oid of this parameter. 31 | * @see org.postgresql.Oid 32 | */ 33 | public function get typeOid():int { 34 | return _oid; 35 | } 36 | 37 | /** 38 | * The raw bytes for this parameter value, as encoded according to the 39 | * specified format. 40 | */ 41 | public function get value():ByteArray { 42 | return _value; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/event/NoticeEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.event { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * Indicates a notice or error sent by the server. 7 | */ 8 | public class NoticeEvent extends Event { 9 | 10 | /** 11 | * A notice (informational) message from PostgreSQL. 12 | * 13 | * @eventType notice 14 | */ 15 | public static const NOTICE:String = 'notice'; 16 | 17 | /** 18 | * An error message from PostgreSQL. 19 | * 20 | * @eventType error 21 | */ 22 | public static const ERROR:String = 'error'; 23 | 24 | private var _fields:Object; 25 | 26 | /** 27 | * Details of the message, as a map of notice field code to corresponding message. 28 | * 29 | * @see org.postgresql.NoticeFields 30 | */ 31 | public function get fields():Object { 32 | return _fields; 33 | } 34 | 35 | /** 36 | * Create a new notice event. 37 | * 38 | * @param type type of notice 39 | * @param fields fields describing notice 40 | * 41 | * @private 42 | */ 43 | public function NoticeEvent(type:String, fields:Object) { 44 | super(type); 45 | _fields = fields; 46 | } 47 | 48 | } 49 | } -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/functional/SelectTestBase.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.functional { 2 | import org.flexunit.async.Async; 3 | import org.flexunit.asserts.assertNotNull; 4 | import org.postgresql.db.QueryToken; 5 | import org.flexunit.asserts.assertEquals; 6 | import org.postgresql.db.event.QueryResultEvent; 7 | import org.postgresql.db.event.QueryCompletionEvent; 8 | import org.postgresql.db.EventResultHandler; 9 | 10 | public /* asbtract */ class SelectTestBase extends ConnectedTestBase { 11 | 12 | protected function runQuery(verifyFn:Function, sql:String, args:Array=null):void { 13 | var handler:EventResultHandler = new EventResultHandler(); 14 | Async.proceedOnEvent(this, handler, QueryCompletionEvent.COMPLETE, 1000); 15 | 16 | handler.addEventListener(QueryResultEvent.RESULT, verifyFn); 17 | // N.B.: this listener is executing with higher priority that the 'proceed' above 18 | handler.addEventListener(QueryCompletionEvent.COMPLETE, function(e:QueryCompletionEvent):void { 19 | assertEquals(0, e.rows); 20 | assertEquals('SELECT', e.tag); 21 | }); 22 | 23 | var qt:QueryToken = connection.execute(handler, sql, args); 24 | assertNotNull(qt); 25 | assertEquals(qt.sql, sql); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/decode/TextOut.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.decode { 2 | 3 | import org.postgresql.EncodingFormat; 4 | import org.postgresql.codec.IPGTypeDecoder; 5 | import org.postgresql.febe.IFieldInfo; 6 | import org.postgresql.io.ICDataInput; 7 | 8 | /** 9 | * Parse the text representation of a PostgreSQL type into an ActionScript String; 10 | * used to decode text or varchar types. 11 | */ 12 | public class TextOut implements IPGTypeDecoder { 13 | 14 | /** 15 | * @inheritDoc 16 | */ 17 | public function decode(bytes:ICDataInput, format:IFieldInfo, serverParams:Object):Object { 18 | switch (format.format) { 19 | case EncodingFormat.TEXT: 20 | return bytes.readUTFBytes(bytes.bytesAvailable); 21 | case EncodingFormat.BINARY: 22 | throw new ArgumentError("Unsupported format: " + format.format); 23 | default: 24 | throw new ArgumentError("Unknown format: " + format.format); 25 | } 26 | } 27 | 28 | /** 29 | * This decoder returns String. 30 | * 31 | * @see String 32 | */ 33 | public function getOutputClass(typeOid:int):Class { 34 | return String; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/encode/TextIn.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.encode { 2 | import org.postgresql.UnsupportedProtocolFeatureError; 3 | import org.postgresql.EncodingFormat; 4 | import org.postgresql.Oid; 5 | import org.postgresql.codec.IPGTypeEncoder; 6 | import org.postgresql.io.ICDataOutput; 7 | 8 | /** 9 | * Encodes ActionScript Strings into PostgreSQL text values. 10 | */ 11 | public class TextIn implements IPGTypeEncoder { 12 | 13 | /** 14 | * @inheritDoc 15 | */ 16 | public function encode(bytes:ICDataOutput, value:Object, format:int, serverParams:Object):void { 17 | switch (format) { 18 | case EncodingFormat.TEXT: 19 | bytes.writeUTFBytes(String(value)); 20 | break; 21 | case EncodingFormat.BINARY: 22 | throw new UnsupportedProtocolFeatureError("Binary format not supported"); 23 | break; 24 | default: 25 | throw new ArgumentError("Unknown format: " + format); 26 | } 27 | } 28 | 29 | /** 30 | * This encoder returns Oid.TEXT. 31 | * 32 | * @see org.postgresql.Oid#TEXT 33 | */ 34 | public function getInputOid(clazz:Class):int { 35 | return Oid.TEXT; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/encode/Float8In.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.encode { 2 | import org.postgresql.EncodingFormat; 3 | import org.postgresql.Oid; 4 | import org.postgresql.codec.IPGTypeEncoder; 5 | import org.postgresql.io.ICDataOutput; 6 | 7 | /** 8 | * Encodes ActionScript Numbers into PostgreSQL float8 (double precision) 9 | * values. 10 | */ 11 | public class Float8In implements IPGTypeEncoder { 12 | 13 | /** 14 | * @inheritDoc 15 | */ 16 | public function encode(bytes:ICDataOutput, value:Object, format:int, serverParams:Object):void { 17 | switch (format) { 18 | case EncodingFormat.TEXT: 19 | var numStr:String = Number(value).toString(); 20 | bytes.writeUTFBytes(numStr); 21 | break; 22 | case EncodingFormat.BINARY: 23 | bytes.writeDouble(Number(value)); 24 | break; 25 | default: 26 | throw new ArgumentError("Unknown format: " + format); 27 | } 28 | } 29 | 30 | /** 31 | * This encoder returns Oid.FLOAT8. 32 | * 33 | * @see org.postgresql.Oid#FLOAT8 34 | */ 35 | public function getInputOid(clazz:Class):int { 36 | return Oid.FLOAT8; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/functional/ConnectedTestBase.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.functional { 2 | import flash.events.IEventDispatcher; 3 | import org.flexunit.async.Async; 4 | import org.postgresql.db.ConnectionFactory; 5 | import org.postgresql.db.IConnection; 6 | import org.postgresql.event.ConnectionEvent; 7 | import org.postgresql.log.ILogger; 8 | import org.postgresql.log.Log; 9 | import org.postgresql.pegasus.Credentials; 10 | 11 | public /* abstract */ class ConnectedTestBase { 12 | 13 | private const LOGGER:ILogger = Log.getLogger(Object(this).constructor as Class); 14 | 15 | protected var connection:IConnection; 16 | 17 | [Before(async,timeout=1000)] 18 | public function setup():void { 19 | LOGGER.debug("Creating connection."); 20 | connection = new ConnectionFactory().createConnection(Credentials.url, Credentials.user, Credentials.password); 21 | // TODO: register failure event on Connection error 22 | Async.proceedOnEvent(this, IEventDispatcher(connection), ConnectionEvent.CONNECTED); 23 | LOGGER.debug("Created"); 24 | } 25 | 26 | [After(async,timeout=1000)] 27 | public function tearDown():void { 28 | LOGGER.debug("Closing connection."); 29 | connection.close(); 30 | connection = null; 31 | LOGGER.debug("Closed."); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/event/ParameterChangeEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.event { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * Indicates a change in a server configuration paramter. 7 | */ 8 | public class ParameterChangeEvent extends Event { 9 | 10 | /** 11 | * A parameter change in a PostgreSQL configuration parameter. 12 | */ 13 | public static const PARAMETER_CHANGE:String = 'parameterChange'; 14 | 15 | private var _name:String; 16 | private var _value:String; 17 | 18 | /** 19 | * Name of parameter that has changed. 20 | */ 21 | public function get name():String { 22 | return _name; 23 | } 24 | 25 | /** 26 | * New value for the parameter. Note that this is a string representation 27 | * of the value, even for numeric parameters. 28 | */ 29 | public function get value():String { 30 | return _value; 31 | } 32 | 33 | /** 34 | * Create a new event 35 | * 36 | * @param name name of parameter which changed 37 | * @param name newValue new value of parameter 38 | * 39 | * @private 40 | */ 41 | public function ParameterChangeEvent(name:String, newValue:String) { 42 | super(PARAMETER_CHANGE); 43 | _name = name; 44 | _value = newValue; 45 | } 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/util/format.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.util { 2 | 3 | /** 4 | * Format the template by substituting any parameter marker with its 5 | * corresponding argument. Parameter markers are defined by a number 6 | * (indicating the argument index to replace) enclosed by curly braces. 7 | *

8 | * E.g., an invocation such as format("{1} {0}!", 'world', 'hello') 9 | * would return the string hello world!. 10 | *

11 | * If the replacement values are not Strings, they are coerced to 12 | * Strings before substitution, as per the String function. 13 | * 14 | * @param template String in which to perform parameter substitution 15 | * @param args arguments to substitute 16 | * @return a String with all token references subtituted with their corresponding values 17 | * @throws ArgumentException if more values are referenced than provided 18 | * @see String 19 | */ 20 | public function format(template:String, ...args):String { 21 | return template.replace(/{(\d+)}/g, function():String { 22 | var replacementIndex:int = int(arguments[1]); 23 | if (replacementIndex > args.length) { 24 | throw new ArgumentError("Invalid log argument index: " + replacementIndex); 25 | } else { 26 | return String(args[replacementIndex]); 27 | } 28 | }); 29 | } 30 | } -------------------------------------------------------------------------------- /pgconsole/src/PGConsole-app.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.postgresql.pgconsole.PGConsole 5 | PGConsole 6 | 1.0 7 | PGConsole-@VERSION@ 8 | 9 | This is a demo application for Pegasus, an ActionScript driver for PostgreSQL. 10 | 11 | Copyright 2009-2011, PostgreSQL Global Development Group 12 | 13 | PGConsole-@VERSION@.swf 14 | PGConsole: A Pegasus Demo 15 | standard 16 | false 17 | true 18 | true 19 | true 20 | true 21 | 1100 22 | 500 23 | 150 24 | 150 25 | 550 400 26 | 1600 1000 27 | 28 | pegasus/pgconsole 29 | pegasus/pgconsole 30 | 31 | false 32 | false 33 | 34 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/component/QueryResponseRenderer.mxml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 1 ? " rows" : " row"; 14 | resultText.text += ". Returned " + responseVO.data.length + rowStr; 15 | autoDrawBackground = true; 16 | } else { 17 | autoDrawBackground = false; 18 | } 19 | } else { 20 | resultText.text = ''; 21 | autoDrawBackground = false; 22 | } 23 | } 24 | ]]> 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/encode/BoolIn.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.encode { 2 | import org.postgresql.Oid; 3 | import org.postgresql.UnsupportedProtocolFeatureError; 4 | import org.postgresql.EncodingFormat; 5 | import org.postgresql.codec.IPGTypeEncoder; 6 | import org.postgresql.io.ICDataOutput; 7 | 8 | /** 9 | * Encodes ActionScript Booleans into PostgreSQL bool values. 10 | */ 11 | public class BoolIn implements IPGTypeEncoder { 12 | 13 | /** 14 | * @inheritDoc 15 | */ 16 | public function encode(bytes:ICDataOutput, value:Object, format:int, serverParams:Object):void { 17 | switch (format) { 18 | case EncodingFormat.TEXT: 19 | var boolStr:String = Boolean(value) ? 't' : 'f'; 20 | bytes.writeUTFBytes(boolStr); 21 | break; 22 | case EncodingFormat.BINARY: 23 | throw new UnsupportedProtocolFeatureError("Binary format not supported"); 24 | break; 25 | default: 26 | throw new ArgumentError("Unknown format: " + format); 27 | } 28 | } 29 | 30 | /** 31 | * This encoder returns Oid.BOOL. 32 | * 33 | * @see org.postgresql.Oid#BOOL 34 | */ 35 | public function getInputOid(clazz:Class):int { 36 | return Oid.BOOL; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Parse.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.io.ICDataOutput; 4 | 5 | public class Parse extends AbstractMessage implements IFEMessage { 6 | 7 | public var statement:String; 8 | public var sql:String; 9 | public var paramOids:Array; 10 | 11 | public function Parse(statement:String, sql:String, paramOids:Array) { 12 | if (statement == null || sql == null || paramOids == null) { 13 | throw new ArgumentError("statement, sql, and paramOids must not be null"); 14 | } 15 | this.statement = statement; 16 | this.sql = sql; 17 | this.paramOids = paramOids; 18 | } 19 | 20 | public function write(out:ICDataOutput):void { 21 | out.writeByte(code('P')); 22 | var len:int = 4 + statement.length + 1 + sql.length + 1 + 2 + 4 * paramOids.length; 23 | out.writeInt(len); 24 | out.writeCString(statement); 25 | out.writeCString(sql); 26 | out.writeShort(paramOids.length); 27 | for each (var oid:int in paramOids) { 28 | out.writeInt(oid); 29 | } 30 | } 31 | 32 | override public function toString():String { 33 | return super.toString() + ' {' + (statement.length > 0 ? statement : '[unnamed]: ') + 34 | sql + '; paramOids[' + paramOids.join(',') + ']}'; 35 | } 36 | 37 | } 38 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/util/getType.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.util { 2 | 3 | import flash.utils.getDefinitionByName; 4 | import flash.utils.getQualifiedClassName; 5 | 6 | /** 7 | * Determine the type of the given Object. Note that at the moment, due to some 8 | * Flash Player shenanigans, this does not work well with numeric types (int, 9 | * uint, and Number). We take the pragmatic approach that anything 10 | * numeric that fits in 32 bits and is integral is an int, and all other numeric 11 | * values are considered Number. 12 | * @param value Object whose class to determine; must not be null 13 | * @return Class of the given object 14 | */ 15 | public function getType(value:Object):Class { 16 | if (value == null) { 17 | throw new ArgumentError("Cannot determine type of null value"); 18 | } else if (value is XMLList || value is XML) { 19 | // Note that XMLList and XML don't play nice with .constructor. There's odd 20 | // behavior with numeric types as well, but that seems more difficult to 21 | // work around. Will revisit. 22 | var fqcn:String = getQualifiedClassName(value); 23 | return Class(getDefinitionByName(fqcn)); 24 | } else if (value is int) { 25 | return int; 26 | } else { 27 | return Class(value.constructor); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/util/TestPgURL.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.util { 2 | 3 | import org.flexunit.Assert; 4 | import org.postgresql.PgURL; 5 | 6 | [RunWith("org.flexunit.runners.Parameterized")] 7 | public class TestPgURL { 8 | 9 | public static function getTestURLs():Array { 10 | return [ 11 | [ 'asdbc:postgresql://localhost/pegasus', 'localhost', 5432, 'pegasus', {} ], 12 | [ 'asdbc:postgresql://example.com/pegasus', 'example.com', 5432, 'pegasus', {} ], 13 | [ 'asdbc:postgresql://localhost:1234/pegasus', 'localhost', 1234, 'pegasus', {} ], 14 | [ 'asdbc:postgresql://localhost/testdb', 'localhost', 5432, 'testdb', {} ], 15 | [ 'asdbc:postgresql://localhost/pegasus?param1=hello¶m2=world', 'localhost', 5432, 'pegasus', { 16 | param1: 'hello', param2: 'world' 17 | } ] 18 | ]; 19 | } 20 | 21 | [Test(dataProvider="getTestURLs")] 22 | public function testURL(url:String, host:String, port:int, db:String, params:Object):void { 23 | var pgUrl:PgURL = new PgURL(url); 24 | Assert.assertEquals(host, pgUrl.host); 25 | Assert.assertEquals(port, pgUrl.port); 26 | Assert.assertEquals(db, pgUrl.db); 27 | for (var key:String in params) { 28 | Assert.assertEquals(params[key], pgUrl.parameters[key]); 29 | } 30 | } 31 | 32 | } 33 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/QueryResultView.mxml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/event/NotificationEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.event { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * A notification sent by the server as part of PostgreSQL's LISTEN / NOTIFY 7 | * functionality. 8 | */ 9 | public class NotificationEvent extends Event { 10 | 11 | /** 12 | * A notification through the PostgreSQL LISTEN / NOTIFY protocol. 13 | * 14 | * @eventType notification 15 | */ 16 | public static const NOTIFICATION:String = 'notification'; 17 | 18 | private var _notifierPid:int; 19 | private var _condition:String; 20 | 21 | /** 22 | * The LISTEN condition. 23 | */ 24 | public function get condition():String { 25 | return _condition; 26 | } 27 | 28 | /** 29 | * The processs identifier of the notifying process 30 | */ 31 | public function get notifierPid():int { 32 | return _notifierPid; 33 | } 34 | 35 | /** 36 | * Create a new notification event 37 | * 38 | * @param condition condition corresponding to this notification 39 | * @param notifierPid pid of notifying process 40 | * 41 | * @private 42 | */ 43 | public function NotificationEvent(condition:String, notifierPid:int) { 44 | super(NOTIFICATION, false, false); 45 | _condition = condition; 46 | _notifierPid = notifierPid; 47 | } 48 | 49 | } 50 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/impl/QueryHandlerFactory.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db.impl { 2 | import org.postgresql.codec.CodecFactory; 3 | import org.postgresql.db.IResultHandler; 4 | import org.postgresql.febe.IExtendedQueryHandler; 5 | import org.postgresql.febe.IQueryHandler; 6 | 7 | /** 8 | * Factory for creating new query handlers. 9 | */ 10 | public class QueryHandlerFactory { 11 | 12 | private var _codecFactory:CodecFactory; 13 | 14 | /** 15 | * Constructor. 16 | * 17 | * @param codecFactory CodecFactory to use 18 | */ 19 | public function QueryHandlerFactory(codecFactory:CodecFactory) { 20 | _codecFactory = codecFactory; 21 | } 22 | 23 | /** 24 | * Create new IQueryHandler wiht the given IResultHandler. 25 | * 26 | * @param resultHandler IResultHandler to use 27 | */ 28 | public function createSimpleHandler(resultHandler:IResultHandler):IQueryHandler { 29 | return new SimpleQueryHandler(resultHandler, _codecFactory); 30 | } 31 | 32 | /** 33 | * Create a new IExtendedQueryHandler with the given IResultHanlder. 34 | * 35 | * @param resultHandler IResultHandler to use 36 | */ 37 | public function createExtendedHandler(resultHandler:IResultHandler):IExtendedQueryHandler { 38 | return new ExtendedQueryHandler(resultHandler, _codecFactory); 39 | } 40 | 41 | } 42 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/decode/BoolOut.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.decode { 2 | import org.postgresql.Oid; 3 | import org.postgresql.EncodingFormat; 4 | import org.postgresql.codec.IPGTypeDecoder; 5 | import org.postgresql.febe.IFieldInfo; 6 | import org.postgresql.io.ICDataInput; 7 | 8 | /** 9 | * Parse a PostgreSQL bool into an ActionScript Boolean. 10 | */ 11 | public class BoolOut implements IPGTypeDecoder { 12 | /** 13 | * @inheritDoc 14 | */ 15 | public function decode(bytes:ICDataInput, format:IFieldInfo, serverParams:Object):Object { 16 | switch (format.format) { 17 | case EncodingFormat.TEXT: 18 | return Boolean(bytes.readUTFBytes(bytes.bytesAvailable)); 19 | case EncodingFormat.BINARY: 20 | switch (format.typeOid) { 21 | case Oid.BOOL: 22 | return bytes.readBoolean(); 23 | default: 24 | throw new ArgumentError("Unable to decode oid: " + format.typeOid); 25 | } 26 | default: 27 | throw new ArgumentError("Unknown format: " + format.format); 28 | } 29 | } 30 | 31 | /** 32 | * This decoder returns Boolean. 33 | * @see Boolean 34 | */ 35 | public function getOutputClass(typeOid:int):Class { 36 | return Boolean; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/Oid.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * OIDs for all the main PostgreSQL data types. Note that this 5 | * is not an exhaustive list--it's merely a convenient 6 | * way to reference the most common OIDs. 7 | */ 8 | public class Oid { 9 | public static const UNSPECIFIED:int = 0; 10 | public static const INT2:int = 21; 11 | public static const INT4:int = 23; 12 | public static const INT8:int = 20; 13 | public static const TEXT:int = 25; 14 | public static const NUMERIC:int = 1700; 15 | public static const FLOAT4:int = 700; 16 | public static const FLOAT8:int = 701; 17 | public static const BOOL:int = 16; 18 | public static const DATE:int = 1082; 19 | public static const TIME:int = 1083; 20 | public static const TIMETZ:int = 1266; 21 | public static const TIMESTAMP:int = 1114; 22 | public static const TIMESTAMPTZ:int = 1184; 23 | public static const BYTEA:int = 17; 24 | public static const VARCHAR:int = 1043; 25 | public static const OID:int = 26; 26 | public static const BPCHAR:int = 1042; 27 | public static const MONEY:int = 790; 28 | public static const NAME:int = 19; 29 | public static const BIT:int = 1560; 30 | public static const VOID:int = 2278; 31 | public static const INTERVAL:int = 1186; 32 | public static const CHAR:int = 18; // (single char) 33 | public static const VARBIT:int = 1562; 34 | public static const UNKNOWN:int = 705; 35 | } 36 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2011, PostgreSQL Global Development Group 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 3. Neither the name of the PostgreSQL Global Development Group nor the names 13 | of its contributors may be used to endorse or promote products derived 14 | from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/log/ILogTarget.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.log { 2 | /** 3 | * An ILogTarget receives log messages from the logging framework and 4 | * publishes them for consumption by an end user. This can be achieved through trace 5 | * statement, browser integration through ExternalInterface, shipping 6 | * to the back-end, or any other such means. The ILogTarget should format 7 | * the incoming messages according to the configured format string. 8 | */ 9 | public interface ILogTarget { 10 | /** 11 | * Format string: 12 | *

13 |          *    %d    date in YYYY-MM-DD format
14 |          *    %t    time in HH:MM:SS format
15 |          *    %l    log level
16 |          *    %c    category
17 |          *    %m    method
18 |          *    %n    line number
19 |          *    %s    message
20 |          * 
21 | * All other characters are printed literally. These format specifications cannot 22 | * be escaped; the corresponding characters always convey formatting information. 23 | * 24 | * @param value format to use 25 | */ 26 | function set format(value:String):void; 27 | /** 28 | * Handle the given message according to the currently configured format. Note that 29 | * if method and line number are used in the format String, it is the ILogTarget's 30 | * responsibility to determine this information. 31 | */ 32 | function handleMessage(level:int, category:String, msg:String):void; 33 | } 34 | } -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/util/TestGetType.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.util { 2 | 3 | import org.flexunit.Assert; 4 | import org.postgresql.util.getType; 5 | 6 | [RunWith("org.flexunit.runners.Parameterized")] 7 | public class TestGetType { 8 | 9 | public static function getTestTypes():Array { 10 | return [ 11 | [ Number(42), int ], 12 | /* 13 | * The behavior for int, uint and Number is *really* weird. Essentially, AS3 seems 14 | * to veer away from straight static typing here and do a sort of numerical 15 | * duck typing. The .constructor property for variables typed as int, uint, and 16 | * Number always returns Number, and the 'is' operator returns true if the given 17 | * number can be expressed with that type. E.g., (Number(42) is int) and 18 | * uint(42) is Number) are both true. Will add additional tests once getType 19 | * supports these types properly. 20 | 21 | [ uint(42), uint ], 22 | [ Number(42), Number ], 23 | 24 | */ 25 | [ new Date(), Date ], 26 | [ 'hello world', String ], 27 | [ , XML ], 28 | [ XMLList(), XMLList ] 29 | ]; 30 | } 31 | 32 | [Test(dataProvider="getTestTypes")] 33 | public function testGetType(value:Object, expectedType:Class):void { 34 | var type:Class = getType(value); 35 | Assert.assertEquals(expectedType, type); 36 | } 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /test/src/PegasusTest.mxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/decode/IntOut.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.decode { 2 | 3 | import org.postgresql.EncodingFormat; 4 | import org.postgresql.Oid; 5 | import org.postgresql.codec.IPGTypeDecoder; 6 | import org.postgresql.febe.IFieldInfo; 7 | import org.postgresql.io.ICDataInput; 8 | 9 | /** 10 | * Parse a PostgreSQL int4 or int2 value into an ActionScript 11 | * int. 12 | */ 13 | public class IntOut implements IPGTypeDecoder { 14 | 15 | /** 16 | * @inheritDoc 17 | */ 18 | public function decode(bytes:ICDataInput, format:IFieldInfo, serverParams:Object):Object { 19 | switch (format.format) { 20 | case EncodingFormat.TEXT: 21 | return int(bytes.readUTFBytes(bytes.bytesAvailable)); 22 | case EncodingFormat.BINARY: 23 | switch (format.typeOid) { 24 | case Oid.INT2: 25 | return bytes.readShort(); 26 | case Oid.INT4: 27 | return bytes.readInt(); 28 | default: 29 | throw new ArgumentError("Unable to decode oid: " + format.typeOid); 30 | } 31 | default: 32 | throw new ArgumentError("Unknown format: " + format.format); 33 | } 34 | } 35 | 36 | /** 37 | * This decoder returns int. 38 | * @see int 39 | */ 40 | public function getOutputClass(typeOid:int):Class { 41 | return int; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/IOUtil.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | import flash.utils.IDataInput; 4 | import flash.utils.IDataOutput; 5 | 6 | /** 7 | * Internal helper class for stream method implementations. Ideally, these would 8 | * be shared in a better manner, but this is te simplest way to simplify implementation 9 | * across classes with distinct inheritance hierarchies. 10 | */ 11 | internal class IOUtil { 12 | 13 | /** 14 | * Standard implementation for the readCString method on an 15 | * ICDataInput using underlying methods from 16 | * IDataInput. 17 | * 18 | * @param stream stream to read from 19 | * @return the String read 20 | */ 21 | public static function readCString(stream:IDataInput):String { 22 | var strBytes:Array = []; 23 | var currByte:int; 24 | while ((currByte = stream.readByte()) != 0) { 25 | strBytes.push(currByte); 26 | } 27 | return String.fromCharCode.apply(null, strBytes); 28 | } 29 | 30 | 31 | /** 32 | * Standard implementation for the writeCString method on an 33 | * ICDataOutput using underlying methods from 34 | * IDataOutput. 35 | * 36 | * @param stream stream to write to 37 | * @param str String to write 38 | */ 39 | public static function writeCString(stream:IDataOutput, str:String):void { 40 | stream.writeUTFBytes(str); 41 | stream.writeByte(0x00); 42 | } 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/event/QueryResultEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db.event { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * Indicates the result of a SELECT query, or another query which 7 | * returns data. 8 | */ 9 | public class QueryResultEvent extends Event { 10 | 11 | /** 12 | * A query result. 13 | * 14 | * @eventType queryResult 15 | */ 16 | public static const RESULT:String = 'queryResult'; 17 | 18 | private var _columns:Array; 19 | private var _data:Array; 20 | 21 | /** 22 | * Create a new query result event 23 | * 24 | * @param type type of event 25 | * @param columns Array of IColumn instances describing the query results 26 | * @param data Array of Objects containing the query results 27 | * 28 | * @private 29 | */ 30 | public function QueryResultEvent(type:String, columns:Array, data:Array) { 31 | super(type, false, false); 32 | _data = data; 33 | _columns = columns; 34 | } 35 | 36 | /** 37 | * Columns describing the data. 38 | * 39 | * @see org.postgresql.db.ResultHandlerBase#columns 40 | */ 41 | public function get columns():Array { 42 | return _columns; 43 | } 44 | 45 | /** 46 | * Query results. 47 | * 48 | * @see org.postgresql.db.ResultHandlerBase#data 49 | */ 50 | public function get data():Array { 51 | return _data; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/IPGTypeEncoder.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec { 2 | 3 | import org.postgresql.io.ICDataOutput; 4 | 5 | /** 6 | * Encodes ActionScript objects into corresponding PostgreSQL types. 7 | */ 8 | public interface IPGTypeEncoder { 9 | /** 10 | * Encode the given value into the provided byte array. The encoding 11 | * may need to take the server parameters into account. Note that null 12 | * values will never be passed to the encoder (they always encode to 13 | * NULL). 14 | *
15 | * Note that if an error is encountered in encoding or the field cannot 16 | * be encoded for any other reason, this method should throw an Error 17 | * (or one of its subtypes). It typically should not be a CodecError; 18 | * the caller will provide that wrapper as appropriate. 19 | * @param bytes the ByteArray to which the encoded value should be written 20 | * @param value value to encode 21 | * @param format format in which value should be encoded 22 | * @param serverParams the current values of the server parameters 23 | * @see org.postgresql.EncodingFormat 24 | */ 25 | function encode(bytes:ICDataOutput, value:Object, format:int, serverParams:Object):void; 26 | /** 27 | * Indicate the oid of the PostgreSQL type values will be encoded to. 28 | * 29 | * @param clazz Class of value to be encoded 30 | * @return the oid of the encoded value 31 | */ 32 | function getInputOid(clazz:Class):int; 33 | } 34 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/model/MainViewPresentationModel.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.view.model { 2 | import org.postgresql.pgconsole.model.vo.ConnectionAttemptVO; 3 | import org.postgresql.pgconsole.signal.ConnectSignal; 4 | import org.postgresql.pgconsole.signal.DisconnectedSignal; 5 | import org.postgresql.pgconsole.signal.ConnectedSignal; 6 | 7 | public class MainViewPresentationModel { 8 | 9 | [Inject] 10 | public var connectedSignal:ConnectedSignal; 11 | [Inject] 12 | public var disconnectedSignal:DisconnectedSignal; 13 | 14 | [Inject] 15 | public var connectSignal:ConnectSignal; 16 | 17 | [PostConstruct] 18 | public function initialize():void { 19 | connectedSignal.add(onConnected); 20 | disconnectedSignal.add(onDisconnected); 21 | } 22 | 23 | private function onDisconnected():void { 24 | currentState = 'disconnected'; 25 | } 26 | 27 | private function onConnected():void { 28 | currentState = 'connected'; 29 | } 30 | 31 | [Bindable] 32 | public var currentState:String; 33 | 34 | public function logIn(host:String, port:uint, db:String, username:String, password:String):void { 35 | connectSignal.dispatch(new ConnectionAttemptVO(buildUrl(host, port, db), username, password)); 36 | } 37 | 38 | private function buildUrl(host:String, port:uint, db:String):String { 39 | // TODO: proper validation 40 | var url:String = 'asdbc:postgresql://' + host + ':' + port + '/' + db; 41 | trace('Connecting to', url); 42 | return url; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/codec/decode/TestDecodeDate.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.codec.decode { 2 | import org.flexunit.Assert; 3 | import org.postgresql.DateStyle; 4 | import org.postgresql.EncodingFormat; 5 | import org.postgresql.Oid; 6 | import org.postgresql.codec.decode.DateOut; 7 | import org.postgresql.febe.BasicFieldDescription; 8 | import org.postgresql.febe.IFieldInfo; 9 | import org.postgresql.io.ByteDataStream; 10 | import org.postgresql.util.DateUtil; 11 | 12 | [RunWith("org.flexunit.runners.Parameterized")] 13 | public class TestDecodeDate { 14 | private var _decoder:DateOut; 15 | 16 | [Before] 17 | public function setup():void { 18 | _decoder = new DateOut(); 19 | } 20 | 21 | public static function getTestDates():Array { 22 | var format:BasicFieldDescription = new BasicFieldDescription(Oid.TIMESTAMP, EncodingFormat.TEXT); 23 | var params:Object = { DateStyle: DateStyle.OUTPUT_ISO + ', ' + DateStyle.ORDER_YMD }; 24 | return [ 25 | [ getBytes('2000-01-01 00:00:00'), format, params, new Date(2000, 0, 1, 0, 0, 0) ], 26 | [ getBytes('infinity'), format, params, new Date(DateUtil.MAX_DATE_TICKS) ], 27 | [ getBytes('-infinity'), format, params, new Date(DateUtil.MIN_DATE_TICKS) ] 28 | ]; 29 | } 30 | 31 | [Test(dataProvider="getTestDates")] 32 | public function testDecodeTimestamp(bytes:ByteDataStream, format:IFieldInfo, serverParams:Object, expected:Date):void { 33 | var result:Date = _decoder.decode(bytes, format, serverParams) as Date; 34 | Assert.assertEquals(expected.time, result.time); 35 | } 36 | 37 | } 38 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/IPGTypeDecoder.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec { 2 | 3 | import org.postgresql.febe.IFieldInfo; 4 | import org.postgresql.io.ICDataInput; 5 | 6 | /** 7 | * Decodes PostgreSQL types into corresponding ActionScript objects. 8 | */ 9 | public interface IPGTypeDecoder { 10 | /** 11 | * Decode the given value from the encoded byte array. The encoding 12 | * may be defined by the field description and server parameters. 13 | * Note that NULL values will never be passed to the decoder 14 | * (they always decode to null). 15 | *
16 | * Note that if an error is encountered in decoding or the field cannot 17 | * be decoded for any other reason, this method should throw an Error 18 | * (or one of its subtypes). It typically should not be a CodecError; 19 | * the caller will provide that wrapper as appropriate. 20 | * 21 | * @param bytes byte stream encoding a given field 22 | * @param format metadata for the given field as provided by PostgreSQL 23 | * @param serverParams the server parameters at the time the value is being decoded 24 | */ 25 | function decode(bytes:ICDataInput, format:IFieldInfo, serverParams:Object):Object; 26 | /** 27 | * Indicate which ActionScript Class will be produced by this decoder 28 | * for the given PostgreSQL data type. 29 | * 30 | * @param typeOid PostgreSQL type to be decoded 31 | * @return Class as which this oid will be decoded 32 | */ 33 | function getOutputClass(typeOid:int):Class; 34 | } 35 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/NoticeFields.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * Field names and corresponding field codes which 5 | * may occur in notice and error messages from PostgreSQL. 6 | */ 7 | public class NoticeFields { 8 | 9 | private static const FIELD_DESCRIPTIONS:Object = { 10 | S : 'SEVERITY', 11 | C : 'CODE', 12 | M : 'MESSAGE', 13 | D : 'DETAIL', 14 | H : 'HINT', 15 | P : 'POSITION', 16 | p : 'INTERNAL POSITION', 17 | q : 'INTERNAL QUERY', 18 | W : 'WHERE', 19 | F : 'FILE', 20 | L : 'LINE', 21 | R : 'ROUTINE' 22 | }; 23 | 24 | public static const SEVERITY:String = 'S'; 25 | public static const CODE:String = 'C'; 26 | public static const MESSAGE:String = 'M'; 27 | public static const DETAIL:String = 'D'; 28 | public static const HINT:String = 'H'; 29 | public static const POSITION:String = 'P'; 30 | public static const INTERNAL_POSITION:String = 'p'; 31 | public static const INTERNAL_QUERY:String = 'q'; 32 | public static const WHERE:String = 'W'; 33 | public static const FILE:String = 'F'; 34 | public static const LINE:String = 'L'; 35 | public static const ROUTINE:String = 'R'; 36 | 37 | /** 38 | * Describe a notice field type based on its code. 39 | * 40 | * @param fieldCode field code to look up 41 | * @return field description, or null if field code is not recognized 42 | */ 43 | public static function describe(fieldCode:String):String { 44 | return FIELD_DESCRIPTIONS[fieldCode]; 45 | } 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/log/LogLevel.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.log { 2 | 3 | /** 4 | * Class defining constants for various logging level values 5 | */ 6 | public class LogLevel { 7 | 8 | /** 9 | * Detailed debugging output 10 | */ 11 | public static const FINE:int = 0; 12 | /** 13 | * Normal debugging output 14 | */ 15 | public static const DEBUG:int = 1; 16 | /** 17 | * Standard informational messages 18 | */ 19 | public static const INFO:int = 2; 20 | /** 21 | * Warnings 22 | */ 23 | public static const WARN:int = 3; 24 | /** 25 | * Non-fatal errors 26 | */ 27 | public static const ERROR:int = 4; 28 | /** 29 | * Fatal errors 30 | */ 31 | public static const FATAL:int = 5; 32 | /** 33 | * Level used to indicate that no logging output should be produced. 34 | */ 35 | public static const NONE:int = int.MAX_VALUE; 36 | 37 | /** 38 | * String representation of given LogLevel 39 | * 40 | * @param LogLevel to describe 41 | * @return String description of given level 42 | */ 43 | public static function toString(level:int):String { 44 | switch (level) { 45 | case FINE: return 'FINE'; 46 | case DEBUG: return 'DEBUG'; 47 | case INFO: return 'INFO'; 48 | case WARN: return 'WARN'; 49 | case ERROR: return 'ERROR'; 50 | case FATAL: return 'FATAL'; 51 | case NONE: return 'NONE'; 52 | default: return 'UNKNOWN'; 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/model/ConnectionActivityViewPresentationModel.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.view.model { 2 | import org.postgresql.pgconsole.model.activity.vo.QueryActivityResponseVO; 3 | import org.postgresql.pgconsole.model.activity.vo.ConnectionActivityVO; 4 | import org.postgresql.pgconsole.signal.SelectResultsSignal; 5 | import flash.events.Event; 6 | import flash.events.EventDispatcher; 7 | import org.postgresql.pgconsole.signal.ConnectionActivityChangedSignal; 8 | import mx.collections.ArrayCollection; 9 | 10 | public class ConnectionActivityViewPresentationModel extends EventDispatcher { 11 | private var _activity:ArrayCollection; 12 | 13 | [Inject] 14 | public var connectionActivity:ConnectionActivityChangedSignal; 15 | 16 | [Inject] 17 | public var selectResult:SelectResultsSignal; 18 | 19 | [PostConstruct] 20 | public function initialize():void { 21 | connectionActivity.add(onActivityChanged); 22 | _activity = new ArrayCollection(); 23 | } 24 | 25 | private function onActivityChanged(activity:Array):void { 26 | _activity.source = activity; 27 | var lastActivity:ConnectionActivityVO = ConnectionActivityVO(activity[activity.length - 1]); 28 | if (lastActivity is QueryActivityResponseVO) { 29 | selectResult.dispatch(QueryActivityResponseVO(lastActivity)); 30 | } 31 | 32 | dispatchEvent(new Event('activityChanged')); 33 | } 34 | 35 | [Bindable(event='activityChanged')] 36 | public function get activity():ArrayCollection { 37 | return _activity; 38 | } 39 | 40 | public function showResults(data:QueryActivityResponseVO):void { 41 | selectResult.dispatch(data); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/event/ConnectionErrorEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.event { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * An Error related to the connection itself, rather than to any 7 | * queries issued through the connection. 8 | */ 9 | public class ConnectionErrorEvent extends Event { 10 | 11 | /** 12 | * The underlying connection to the PostgreSQL backend was lost. 13 | * 14 | * @eventType connectivityError 15 | */ 16 | public static const CONNECTIVITY_ERROR:String = 'connectivityError'; 17 | 18 | /** 19 | * An error has occurred in the handling of the underlying protocol. 20 | * 21 | * @see org.postgresq.ProtocolError 22 | * 23 | * @eventType protocolError 24 | */ 25 | public static const PROTOCOL_ERROR:String = 'protocolError'; 26 | 27 | /** 28 | * The underlying connection encountered an error in encoding or 29 | * decoding data. This is normally due to the lack of a suitable 30 | * codec, or an error in a codec. 31 | * 32 | * @eventType codecError 33 | */ 34 | public static const CODEC_ERROR:String = 'codecError'; 35 | 36 | private var _cause:Error; 37 | 38 | /** 39 | * Create a new connection error event 40 | * 41 | * @param type type of event 42 | * @param cause Error which triggered the event 43 | * 44 | * @private 45 | */ 46 | public function ConnectionErrorEvent(type:String, cause:Error) { 47 | super(type); 48 | _cause = cause; 49 | } 50 | 51 | /** 52 | * The Error which triggered this Event. 53 | */ 54 | public function get cause():Error { 55 | return _cause; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/encode/AbstractIntIn.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.encode { 2 | import org.postgresql.EncodingFormat; 3 | import org.postgresql.util.AbstractMethodError; 4 | import org.postgresql.codec.IPGTypeEncoder; 5 | import org.postgresql.io.ICDataOutput; 6 | 7 | /** 8 | * Base class for encoding integer types. 9 | */ 10 | public /* abstract */ class AbstractIntIn implements IPGTypeEncoder { 11 | /** 12 | * Base encode method. In TEXT mode, simply writes out the textual representation of 13 | * the integer. In BINARY mode, calls binaryEncodeInt(). 14 | * 15 | * @see #binaryEncodeInt 16 | */ 17 | public function encode(bytes:ICDataOutput, value:Object, format:int, serverParams:Object):void { 18 | switch (format) { 19 | case EncodingFormat.TEXT: 20 | bytes.writeUTFBytes(value.toString()); 21 | break; 22 | case EncodingFormat.BINARY: 23 | binaryEncodeInt(bytes, value, serverParams); 24 | break; 25 | default: 26 | throw new ArgumentError("Unknown format: " + format); 27 | } 28 | 29 | } 30 | 31 | /** 32 | * Encode the given value, as with encode, but mode is always assumed to 33 | * be BINARY when this method is called. Must be overridden by subclass. 34 | */ 35 | protected /* abstract */ function binaryEncodeInt(bytes:ICDataOutput, value:Object, serverParams:Object):void { 36 | throw new AbstractMethodError(); 37 | } 38 | 39 | /** 40 | * Return input oid. Must be overridden by subclass. 41 | */ 42 | public /* abstract */ function getInputOid(clazz:Class):int { 43 | throw new AbstractMethodError(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/log/ILogger.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.log { 2 | /** 3 | * An ILogger allows logging of messages from a given source 4 | * and passes them on to the logging framework (for routing and publishing 5 | * through ILogTargets). 6 | */ 7 | public interface ILogger { 8 | /** 9 | * The category this logger logs messages for. 10 | */ 11 | function get category():String; 12 | /** 13 | * Log a message at the given level. Parameters should be substituted according to 14 | * positional markers. 15 | * 16 | * @param level LogLevel to use 17 | * @param message message to log 18 | * @param rest parameters to substitute, if any 19 | * @see org.postgresql.log.LogLevel 20 | */ 21 | function log(level:int, message:String, ...rest):void; 22 | /** 23 | * Log a message at fine level. 24 | * 25 | * @see #log 26 | */ 27 | function fine(message:String, ...rest):void; 28 | /** 29 | * Log a message at debug level. 30 | * 31 | * @see #log 32 | */ 33 | function debug(message:String, ...rest):void; 34 | /** 35 | * Log a message at info level. 36 | * 37 | * @see #log 38 | */ 39 | function info(message:String, ...rest):void; 40 | /** 41 | * Log a message at warning level. 42 | * 43 | * @see #log 44 | */ 45 | function warn(message:String, ...rest):void; 46 | /** 47 | * Log a message at error level. 48 | * 49 | * @see #log 50 | */ 51 | function error(message:String, ...rest):void; 52 | /** 53 | * Log a message at fatal level. 54 | * 55 | * @see #log 56 | */ 57 | function fatal(message:String, ...rest):void; 58 | } 59 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/FieldDescription.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | import org.postgresql.EncodingFormat; 4 | import org.postgresql.io.ICDataInput; 5 | 6 | /** 7 | * Default IColumnInfo implementation. 8 | */ 9 | public class FieldDescription implements IColumnInfo { 10 | 11 | private var _name:String; 12 | public var tableOid:int; 13 | public var attributeNum:int; 14 | private var _typeOid:int; 15 | public var typeSize:int; 16 | public var typeModifier:int; 17 | private var _format:int; 18 | 19 | /** 20 | * Deserialize according to PostgreSQL field metadata encoding. 21 | * 22 | * @param input ICDataInput containing FieldDescription bytes 23 | */ 24 | public function read(input:ICDataInput):void { 25 | _name = input.readCString(); 26 | tableOid = input.readInt(); 27 | attributeNum = input.readShort(); 28 | _typeOid = input.readInt(); 29 | typeSize = input.readShort(); 30 | typeModifier = input.readInt(); 31 | _format = input.readShort(); 32 | EncodingFormat.validate(format); 33 | } 34 | 35 | /** 36 | * @inheritDoc 37 | */ 38 | public function get typeOid():int { 39 | return _typeOid; 40 | } 41 | 42 | /** 43 | * @inheritDoc 44 | */ 45 | public function get format():int { 46 | return _format; 47 | } 48 | 49 | /** 50 | * @inheritDoc 51 | */ 52 | public function toString():String { 53 | return name + '(oid:' + _typeOid + ',attno:' + attributeNum + ',size:' + typeSize + ',typmod:' + typeModifier + ')'; 54 | } 55 | 56 | /** 57 | * @inheritDoc 58 | */ 59 | public function get name():String { 60 | return _name; 61 | } 62 | 63 | } 64 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/StartupMessage.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IFEMessage; 5 | import org.postgresql.febe.message.MessageError; 6 | import org.postgresql.io.ICDataOutput; 7 | 8 | public class StartupMessage extends AbstractMessage implements IFEMessage { 9 | 10 | private static const PROTOCOL_VERSION:int = 196608; 11 | private var _parameters:Object; 12 | private var _paramLen:int; 13 | 14 | public function StartupMessage(parameters:Object) { 15 | if (!parameters) { 16 | throw new ArgumentError("parameters must not be null"); 17 | } 18 | if (!('user' in parameters)) { 19 | throw new MessageError("StartupMessage must include user", this); 20 | } 21 | _parameters = parameters; 22 | for (var parameter:String in _parameters) { 23 | var value:Object = _parameters[parameter]; 24 | if (!(value is String)) { 25 | value = String(value); 26 | _parameters[parameter] = value; 27 | } 28 | _paramLen += parameter.length + 1 + value.length + 1; 29 | } 30 | } 31 | 32 | public function write(out:ICDataOutput):void { 33 | var len:int = 4 + 4 + _paramLen + 1; 34 | out.writeInt(len); 35 | out.writeInt(PROTOCOL_VERSION); 36 | for (var parameter:String in _parameters) { 37 | out.writeCString(parameter); 38 | out.writeCString(_parameters[parameter]); 39 | } 40 | out.writeByte(0x00); 41 | } 42 | 43 | public override function toString():String { 44 | var items:Array = []; 45 | for (var key:String in _parameters) { 46 | items.push(key + ': ' + _parameters[key]); 47 | } 48 | return super.toString() + ' {' + items.join(', ') + '}'; 49 | } 50 | 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/event/QueryCompletionEvent.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db.event { 2 | 3 | import flash.events.Event; 4 | 5 | /** 6 | * Indicates the completion of a query. 7 | */ 8 | public class QueryCompletionEvent extends Event { 9 | 10 | /** 11 | * A query completion. 12 | * 13 | * @eventType queryComplete 14 | */ 15 | public static const COMPLETE:String = 'queryComplete'; 16 | 17 | private var _tag:String; 18 | private var _rows:int; 19 | private var _oid:int; 20 | 21 | /** 22 | * Create a query completion event. 23 | * 24 | * @param type type of event 25 | * @param tag query completion tag 26 | * @param rows number of rows affected by this query, if applicable 27 | * @param oid oid of inserted row, if applicable 28 | * 29 | * @private 30 | */ 31 | public function QueryCompletionEvent(type:String, tag:String, rows:int, oid:int) { 32 | super(type, false, false); 33 | _tag = tag; 34 | _rows = rows; 35 | _oid = oid; 36 | } 37 | 38 | /** 39 | * Number of rows affected by query. Note that this is not the number of rows returned 40 | * by a SELECT; it corresponds to changes by INSERT, UPDATE, 41 | * and DELETE queries. 42 | */ 43 | public function get rows():int { 44 | return _rows; 45 | } 46 | 47 | /** 48 | * If the query was an INSERT of a single row, and if the target table has oids, 49 | * this contains the oid of the newly-inserted row. Otherwise, it is zero. 50 | */ 51 | public function get oid():int { 52 | return _oid; 53 | } 54 | 55 | /** 56 | * The query completion tag (e.g., SELECT or CREATE TABLE) 57 | */ 58 | public function get tag():String { 59 | return _tag; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/component/QueryRenderer.mxml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 0) { 20 | return args.map(function(item:Object, index:int, array:Array):Object { 21 | return item == null ? 'NULL' : item.toString(); 22 | }).join(', '); 23 | } else { 24 | return '[none]'; 25 | } 26 | } 27 | ]]> 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/QueryInputView.mxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/IMessageStream.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | import flash.events.IEventDispatcher; 4 | import org.postgresql.febe.message.IFEMessage; 5 | 6 | /** 7 | * @eventType org.postgresql.febe.MessageStreamErrorEvent.ERROR 8 | */ 9 | [Event(name="error", type="org.postgresql.febe.MessageStreamErrorEvent")] 10 | /** 11 | * @eventType org.postgresql.febe.MessageStreamEvent.BATCH_COMPLETE 12 | */ 13 | [Event(name="batchComplete", type="org.postgresql.febe.MessageStreamEvent")] 14 | /** 15 | * @eventType org.postgresql.febe.MessageEvent.SENT 16 | */ 17 | [Event(name="messageSent", type="org.postgresql.febe.MessageEvent")] 18 | /** 19 | * @eventType org.postgresql.febe.MessageEvent.RECEIVED 20 | */ 21 | [Event(name="messageReceived", type="org.postgresql.febe.MessageEvent")] 22 | /** 23 | * The IMessageStream interface provides a message-level view of 24 | * a message-oriented application protocol (e.g., FEBE in the case of PostgreSQL). 25 | * A client sends IFEMessage to the server, and the server replies 26 | * with IBEMessages. 27 | *
28 | * A message stream can be considered connected immediately, and stays connected 29 | * until the user calls close(). As with IDataStream, a 30 | * server never initiates a normal disconnect. 31 | * 32 | * @see org.postgresq.febe.message.IFEMessage 33 | * @see org.postgresq.febe.message.IBEMEssage 34 | */ 35 | public interface IMessageStream extends IEventDispatcher { 36 | /** 37 | * Send message to the backend. 38 | * 39 | * @param message IFEMessage to send 40 | * @throws Error if message cannot be sent due to errors in the 41 | * underlying connection 42 | */ 43 | function send(message:IFEMessage):void; 44 | /** 45 | * Close underlying connection to the backend. 46 | */ 47 | function close():void; 48 | /** 49 | * True if this stream is connected; false otherwise. 50 | */ 51 | function get connected():Boolean; 52 | } 53 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/Bind.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import flash.utils.ByteArray; 4 | import org.postgresql.io.ICDataOutput; 5 | 6 | public class Bind extends AbstractMessage implements IFEMessage { 7 | 8 | public var portal:String; 9 | public var statement:String; 10 | public var formats:Array; 11 | public var parameters:Array; 12 | public var resultFormats:Array; 13 | 14 | public function Bind(portal:String, statement:String, formats:Array, parameters:Array, resultFormats:Array) { 15 | this.portal = portal; 16 | this.statement = statement; 17 | this.formats = formats; 18 | this.parameters = parameters; 19 | this.resultFormats = resultFormats; 20 | } 21 | 22 | public function write(out:ICDataOutput):void { 23 | out.writeByte(code('B')); 24 | var len:int = 4 + portal.length + 1 + statement.length + 1 + 2 + (2 * formats.length) + 2; 25 | for each (var param:ByteArray in parameters) { 26 | if (param) { 27 | len += 4 + param.length; 28 | } else { 29 | len += 4; 30 | } 31 | } 32 | len += 2 + (2 * resultFormats.length); 33 | out.writeInt(len); 34 | out.writeCString(portal); 35 | out.writeCString(statement); 36 | out.writeShort(formats.length); 37 | for each (var format:int in formats) { 38 | out.writeShort(format); 39 | } 40 | out.writeShort(parameters.length); 41 | for each (var parameter:ByteArray in parameters) { 42 | if (parameter) { 43 | out.writeInt(parameter.length); 44 | // TODO: is this the right place to reset this? 45 | parameter.position = 0; 46 | out.writeBytes(parameter); 47 | } else { 48 | out.writeInt(-1); 49 | } 50 | } 51 | out.writeShort(resultFormats.length); 52 | for each (var resultFormat:int in resultFormats) { 53 | out.writeShort(resultFormat); 54 | } 55 | 56 | } 57 | 58 | } 59 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/IResultHandler.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db { 2 | 3 | /** 4 | * An IResultHandler manages the results of query execution through a set of 5 | * callbacks. A query which returns data will typically have the following methods involved 6 | * (in this order): 7 | *
    8 | *
  1. handleColumns
  2. 9 | *
  3. handleRow (zero or more times)
  4. 10 | *
  5. handleCompletion
  6. 11 | *
  7. dispose
  8. 12 | *
13 | * A query which does not return data will only have the last two invoked. A query 14 | * which encounters a server-side error will only have dispose invoked. 15 | * A query which encounters an error in decoding will not have handleCompletion 16 | * invoked, and may miss one or more handleRow calls. 17 | */ 18 | public interface IResultHandler { 19 | /** 20 | * Handle the columns describing the results of this query. 21 | * 22 | * @param columns Array of IColumn objects describing the data. 23 | */ 24 | function handleColumns(columns:Array):void; 25 | /** 26 | * Handle an individual data row. 27 | * 28 | * @param rowData Array of column values corresponding to a single row of results 29 | */ 30 | function handleRow(rowData:Array):void; 31 | /** 32 | * Handle the end of query execution. 33 | * 34 | * @param command the PostgreSQL tag specifying the command that just completed, e.g. 35 | * SELECT or INSERT 36 | * @param rows the number of rows affected, or 0 if no rows were affected (e.g., a DDL command) 37 | * @param oid on INSERT, the oid of the inserted row if the target table has oids and 38 | * the insert is a single row, 0 on other INSERT, -1 otherwise 39 | */ 40 | function handleCompletion(command:String, rows:int, oid:int):void; 41 | /** 42 | * Clean up resources associated with this result handler. Note that this method 43 | * is invoked after either successful completion or an error. In either case, 44 | * the handler should clean up. 45 | */ 46 | function dispose():void; 47 | } 48 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/AuthenticationRequest.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import flash.utils.ByteArray; 4 | 5 | import org.postgresql.febe.message.AbstractMessage; 6 | import org.postgresql.febe.message.IBEMessage; 7 | import org.postgresql.febe.message.MessageError; 8 | import org.postgresql.io.ICDataInput; 9 | 10 | /** 11 | * An ugly conglomeration of all the different AuthenticationRequest subtypes. 12 | * This is not pretty, but all the different subtypes are very similar, and 13 | * all share the same message type. It's easier to deal with it like this. 14 | */ 15 | public class AuthenticationRequest extends AbstractMessage implements IBEMessage { 16 | 17 | public var auxdata:ByteArray; 18 | public var subtype:int; 19 | 20 | public static const subtypes:Object = { 21 | '-1': 'Abstract', 22 | '0': 'Ok', 23 | '2': 'KerberosV5', 24 | '3': 'CleartextPassword', 25 | '5': 'MD5Password', 26 | '6': 'SCMCredential', 27 | '7': 'GSS', 28 | '9': 'SSPI', 29 | '8': 'GSSContinue' 30 | }; 31 | 32 | public static const OK:int = 0; 33 | public static const KERBEROS_V5:int = 2; 34 | public static const CLEARTEXT_PASSWORD:int = 3; 35 | public static const MD5_PASSWORD:int = 5; 36 | public static const SCM_CREDENTIAL:int = 6; 37 | public static const GSS:int = 7; 38 | public static const SSPI:int = 9; 39 | public static const GSS_CONTINUE:int = 8; 40 | 41 | public function AuthenticationRequest() { 42 | auxdata = new ByteArray(); 43 | subtype = int.MIN_VALUE; 44 | } 45 | 46 | public override function get type():String { 47 | return 'Authentication' + subtypes[subtype]; 48 | } 49 | 50 | public function read(input:ICDataInput):void { 51 | subtype = input.readInt(); 52 | if (!(subtype in subtypes)) { 53 | throw new MessageError("Unexpected AuthenticationRequest type: " + subtype, this); 54 | } 55 | if (subtype == MD5_PASSWORD || subtype == GSS_CONTINUE) { 56 | input.readBytes(auxdata, 0, input.bytesAvailable); 57 | auxdata.position = 0; 58 | } 59 | } 60 | 61 | } 62 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/model/activity/ConnectionActivityModel.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pgconsole.model.activity { 2 | import org.postgresql.pgconsole.model.activity.vo.NotificationActivityVO; 3 | import org.postgresql.pgconsole.signal.ResultsSelectedSignal; 4 | import org.postgresql.pgconsole.model.activity.vo.QueryActivityResponseVO; 5 | import org.postgresql.pgconsole.model.activity.vo.ConnectionActivityVO; 6 | import org.postgresql.pgconsole.model.activity.vo.NoticeActivityVO; 7 | import org.postgresql.pgconsole.model.activity.vo.QueryActivityVO; 8 | import org.postgresql.pgconsole.model.vo.QueryVO; 9 | import org.postgresql.pgconsole.signal.ConnectionActivityChangedSignal; 10 | import mx.collections.ArrayCollection; 11 | 12 | public class ConnectionActivityModel { 13 | private var _limit:int; 14 | private var _activityList:ArrayCollection; 15 | 16 | [Inject] 17 | public var activityChanged:ConnectionActivityChangedSignal; 18 | [Inject] 19 | public var resultSelected:ResultsSelectedSignal; 20 | 21 | public function ConnectionActivityModel(limit:int=50) { 22 | _limit = limit; 23 | _activityList = new ArrayCollection(); 24 | } 25 | 26 | public function addQuery(query:QueryVO):void { 27 | addActivity(new QueryActivityVO(query.sql, query.args, [])); 28 | } 29 | 30 | public function selectQueryResult(columns:Array, data:Array):void { 31 | resultSelected.dispatch(columns, data); 32 | } 33 | 34 | private function addActivity(activity:ConnectionActivityVO):void { 35 | if (_activityList.length > _limit) { 36 | _activityList.removeItemAt(0); 37 | } 38 | _activityList.addItem(activity); 39 | activityChanged.dispatch(_activityList.source); 40 | } 41 | 42 | public function addNotice(noticeFields:Object):void { 43 | addActivity(new NoticeActivityVO(noticeFields)); 44 | } 45 | 46 | public function addQueryCompletion(tag:String, rows:int, columns:Array, data:Array):void { 47 | addActivity(new QueryActivityResponseVO(tag, rows, columns, data)); 48 | } 49 | 50 | public function addNotification(condition:String, notifierPid:int):void { 51 | addActivity(new NotificationActivityVO(condition, notifierPid)); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/message/CommandComplete.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe.message { 2 | 3 | import org.postgresql.febe.message.AbstractMessage; 4 | import org.postgresql.febe.message.IBEMessage; 5 | import org.postgresql.febe.message.MessageError; 6 | import org.postgresql.io.ICDataInput; 7 | 8 | public class CommandComplete extends AbstractMessage implements IBEMessage { 9 | 10 | public var commandTag:String; 11 | public var command:String; 12 | public var oid:int; 13 | public var affectedRows:int; 14 | 15 | private static const INSERT_CMD:RegExp = /INSERT (\d+) (\d+)/; 16 | private static const COPY_CMD:RegExp = /COPY (\d+)?/; 17 | private static const OTHER_ROW_CMD:RegExp = /(DELETE|UPDATE|MOVE|FETCH) (\d+)/; 18 | 19 | public function CommandComplete() { 20 | oid = -1; 21 | affectedRows = 0; 22 | } 23 | 24 | public function read(input:ICDataInput):void { 25 | commandTag = input.readCString(); 26 | var match:Array; 27 | if (INSERT_CMD.test(commandTag)) { 28 | match = commandTag.match(INSERT_CMD); 29 | if (match.length != 3) { 30 | badTag(commandTag); 31 | } 32 | command = 'INSERT'; 33 | oid = match[1]; 34 | affectedRows = match[2]; 35 | } else if (OTHER_ROW_CMD.test(commandTag)) { 36 | match = commandTag.match(OTHER_ROW_CMD); 37 | if (match.length != 3) { 38 | badTag(commandTag); 39 | } 40 | command = match[1]; 41 | affectedRows = match[2]; 42 | } else if (COPY_CMD.test(commandTag)) { 43 | match = commandTag.match(COPY_CMD); 44 | if (match.length < 2) { 45 | badTag(commandTag); 46 | } 47 | command = 'COPY'; 48 | affectedRows = match.length > 1 ? match.length[1] : -1; 49 | } else { 50 | command = commandTag; 51 | } 52 | } 53 | 54 | private function badTag(tag:String):void { 55 | throw new MessageError("Unexpected command tag: " + tag, this); 56 | } 57 | 58 | override public function toString():String { 59 | return super.toString() + ' {' + commandTag + '}'; 60 | } 61 | 62 | } 63 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/IQueryHandler.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | /** 4 | * This interface defines how to consumer query results from the low-level FEBEConnection. 5 | * The raw protocol-level column metadata is passed to this handler, followed by the raw, un-decoded 6 | * query results. Note that for queries which do not return any results, the handleMetadata 7 | * and handleData methods will not be called. 8 | * @see org.postgresql.febe.FEBEConnection 9 | */ 10 | public interface IQueryHandler { 11 | /** 12 | * Handle the FieldDescription metadata relating to this query. This will be called before 13 | * handleData or handleCompletion. Note that this may be called multiple times if a query 14 | * returns multiple result sets. 15 | * 16 | * @param fields an array of FieldDescription objects. 17 | * @throws org.postgresql.CodecError if an no suitable decoder could be found for one or 18 | * more of the fields 19 | * @see org.postgresql.febe.FieldDescription 20 | */ 21 | function handleMetadata(fields:Array):void; 22 | /** 23 | * Handle the data relating to this query. The argument will be an array of an arbitrary 24 | * number of arrays corresponding to the raw bytes for each field. This method will be called 25 | * zero or more times after each call to handleMetadata before 26 | * handleCompletion is called. 27 | *
28 | * Note that some server parameters, such as DateStyle, can affect the decoding 29 | * process. 30 | * 31 | * @param rows 32 | * @param serverParams 33 | * @throws org.postgresql.CodecError if an error occurred in decoding data 34 | */ 35 | function handleData(rows:Array, serverParams:Object):void; 36 | /** 37 | * Indicates successful completion of a query. After this is called, no other methods on this 38 | * IQueryHandler will be called. 39 | * 40 | * @param command 41 | * @param affected 42 | * @param oid 43 | */ 44 | function handleCompletion(command:String, affected:int=0, oid:int=-1):void; 45 | /** 46 | * Clean up resources associated with this query handler. 47 | */ 48 | function dispose():void; 49 | } 50 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/CodecError.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * Indicates an encoding or decoding error. For communication 5 | * with the backend, data must be encoded and decoded according 6 | * to the protocol specification. This error indicates a failure 7 | * in this process. 8 | *
9 | * This error does not break the connection, but it does 10 | * indicate that the current query has failed. 11 | */ 12 | public class CodecError extends Error { 13 | 14 | /** 15 | * An encoding error. 16 | */ 17 | public static const ENCODE:String = 'encode'; 18 | 19 | /** 20 | * A decoding error. 21 | */ 22 | public static const DECODE:String = 'decode'; 23 | 24 | private var _direction:String; 25 | private var _oid:int; 26 | private var _as3Type:Class; 27 | private var _cause:Error; 28 | 29 | /** 30 | * @private 31 | */ 32 | public function CodecError(message:String, direction:String, cause:Error, oid:int=0 /* Oid.UNSPECIFIED */, as3Type:Class=null) { 33 | super(message); 34 | _direction = direction; 35 | _cause = cause; 36 | _oid = oid; 37 | _as3Type = as3Type; 38 | } 39 | 40 | /** 41 | * Original Error causing this codec error, if any 42 | * 43 | * @return cause, or null if no nested cause 44 | */ 45 | public function get cause():Error { 46 | return _cause; 47 | } 48 | 49 | /** 50 | * If applicable, the ActionScript Class of the destination type (when 51 | * decoding) or the source type (when encoding); otherwise null. 52 | */ 53 | public function get as3Type():Class { 54 | return _as3Type; 55 | } 56 | 57 | /** 58 | * If applicable, the oid of the destination type (when encoding) or 59 | * the source type (when decoding); otherwise Oid.UNSPECIFIED. 60 | * @see org.postgresql.Oid#UNSPECIFIED 61 | */ 62 | public function get oid():int { 63 | return _oid; 64 | } 65 | 66 | /** 67 | * Whether the error was encountered in encoding or decoding. 68 | * @see #ENCODE 69 | * @see #DECODE 70 | */ 71 | public function get direction():String { 72 | return _direction; 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/IExtendedQueryHandler.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | import org.postgresql.febe.IQueryHandler; 3 | 4 | /** 5 | * Handler for the PostgreSQL extended query protocol. 6 | */ 7 | public interface IExtendedQueryHandler extends IQueryHandler { 8 | /** 9 | * For each argument, provide an ArgumentInfo object defining 10 | * encoding format of the argument value, the intended PostgreSQL oid, and 11 | * encoded argument value. 12 | * 13 | * @param args argument values to describe (note that some may be null) 14 | * @param serverParameters values of server parameters at the time 15 | * @return the corresponding argument descriptions 16 | * @see org.postgresql.febe.ArgumentInfo 17 | */ 18 | function describeArguments(args:Array, serverParameters:Object):Array; 19 | /** 20 | * Specify which encoding format(s) should be used to return the results 21 | * of the given query (if any). The descriptions of the query fields may 22 | * be passed to this function, if available. 23 | *

24 | * If field description metadata is not available at the time this function 25 | * is called, null will be passed in, and this function must 26 | * still specify valid encoding formats. 27 | *

28 | * Note that either the number of formats returned must equal the number of 29 | * field descriptions passed in, or a single format to be used for all fields 30 | * must be returned as a one-element Array. 31 | *

32 | * Note: since the number of result fields is not known ahead of time when 33 | * field metadata is not yet available, this method should typically return 34 | * a single format for all fields in these cases (otherwise, the correct 35 | * number of fields must still be provided). 36 | * 37 | * @param fieldDescriptions an Array of IFieldInfo, or 38 | * null if not available 39 | * @return an Array of ints corresponding defining 40 | * the encoding format(s) to use for the results, or containing a single 41 | * format code to use for all result columns 42 | * @see org.postgresql.EncodingFormat 43 | * @see org.postgresql.febe.IFieldInfo 44 | */ 45 | function getOutputFormats(fieldDescriptions:Array):Array; 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/codec/decode/TestDecodeFloat.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.codec.decode { 2 | 3 | import org.flexunit.Assert; 4 | import org.postgresql.EncodingFormat; 5 | import org.postgresql.Oid; 6 | import org.postgresql.codec.decode.FloatOut; 7 | import org.postgresql.febe.BasicFieldDescription; 8 | import org.postgresql.febe.IFieldInfo; 9 | import org.postgresql.io.ByteDataStream; 10 | 11 | [RunWith("org.flexunit.runners.Parameterized")] 12 | public class TestDecodeFloat { 13 | private var _decoder:FloatOut; 14 | 15 | [Before] 16 | public function setup():void { 17 | _decoder = new FloatOut(); 18 | } 19 | 20 | public static function getTestFloats():Array { 21 | var format:BasicFieldDescription = new BasicFieldDescription(Oid.FLOAT4, EncodingFormat.TEXT); 22 | var params:Object = {}; 23 | return [ 24 | [ getBytes('0'), format, params, 0 ], 25 | [ getBytes('1'), format, params, 1 ], 26 | [ getBytes('-1'), format, params, -1 ], 27 | /* 28 | The Number.MAX_VALUE tests fail right now due to some interesting properties of the Flash Player 29 | platform: Number(String(Integer.MAX_VALUE)) != Integer.MAX_VALUE . Not sure if this is a Flash Player 30 | problem or reasonable (but definitely unintuitive) behavior. 31 | [ getBytes(String(Number.MAX_VALUE)), format, params, Number.MAX_VALUE ], 32 | [ getBytes(String(-Number.MAX_VALUE)), format, params, -Number.MAX_VALUE ], 33 | */ 34 | [ getBytes(String(Number.MIN_VALUE)), format, params, Number.MIN_VALUE ], 35 | [ getBytes(String(-Number.MIN_VALUE)), format, params, -Number.MIN_VALUE ], 36 | [ getBytes('Infinity'), format, params, Infinity ], 37 | [ getBytes('-Infinity'), format, params, -Infinity ], 38 | [ getBytes('NaN'), format, params, NaN ] 39 | ]; 40 | } 41 | 42 | [Test(dataProvider="getTestFloats")] 43 | public function testDecodeFloat(bytes:ByteDataStream, format:IFieldInfo, serverParams:Object, expected:Number):void { 44 | var result:Number = _decoder.decode(bytes, format, serverParams) as Number; 45 | // Unfortunately, FlexUnit assertions are still somewhat pathetic 46 | if (isNaN(expected)) { 47 | Assert.assertTrue(isNaN(result)); 48 | } else { 49 | Assert.assertEquals(expected, result); 50 | } 51 | } 52 | 53 | } 54 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/MainView.mxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/encode/TimestamptzIn.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.encode { 2 | import org.postgresql.UnsupportedProtocolFeatureError; 3 | import org.postgresql.Oid; 4 | import org.postgresql.util.DateFormatter; 5 | import org.postgresql.EncodingFormat; 6 | import org.postgresql.codec.IPGTypeEncoder; 7 | import org.postgresql.io.ICDataOutput; 8 | 9 | /** 10 | * Encodes ActionScript Dates into PostgreSQL timestamptz values. 11 | */ 12 | public class TimestamptzIn implements IPGTypeEncoder { 13 | private var _dateFormatter:DateFormatter; 14 | private var _sendUTC:Boolean; 15 | 16 | /** 17 | * Constructor. 18 | * 19 | * @param formatter DateFormatter instance to use for sending timestamps in TEXT-mode 20 | * @param sendUTC whether to send incoming timestamps as UTC or local time 21 | */ 22 | public function TimestamptzIn(formatter:DateFormatter, sendUTC:Boolean) { 23 | _dateFormatter = formatter; 24 | _sendUTC = sendUTC; 25 | } 26 | 27 | /** 28 | * @inheritDoc 29 | */ 30 | public function encode(bytes:ICDataOutput, value:Object, format:int, serverParams:Object):void { 31 | switch (format) { 32 | case EncodingFormat.TEXT: 33 | var dateVal:Date = value as Date; 34 | var formatted:String = _dateFormatter.format(dateVal); 35 | // We need to specify time zone, or PostgreSQL will interpret the timestamp 36 | // in the server time zone, which is rarely what we want. 37 | if (_sendUTC) { 38 | formatted += ' UTC'; 39 | } else { 40 | // The timezone offset uses the somewhat weird format of +/-HMM 41 | formatted += int(dateVal.timezoneOffset / 60) * 100 + (dateVal.timezoneOffset % 60); 42 | } 43 | bytes.writeUTFBytes(formatted); 44 | break; 45 | case EncodingFormat.BINARY: 46 | // See note in DateOut 47 | throw new UnsupportedProtocolFeatureError("Binary format not supported"); 48 | break; 49 | default: 50 | throw new ArgumentError("Unknown format: " + format); 51 | } 52 | } 53 | 54 | /** 55 | * This encoder returns Oid.TIMESTAMPTZ. 56 | * 57 | * @see org.postgresql.Oid#TEXT 58 | */ 59 | public function getInputOid(clazz:Class):int { 60 | return Oid.TIMESTAMPTZ; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/view/ConnectionActivityView.mxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/ByteDataStream.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | import flash.events.Event; 4 | import flash.events.EventDispatcher; 5 | import flash.events.IEventDispatcher; 6 | import flash.utils.ByteArray; 7 | 8 | /** 9 | * An IDataStream backed by a ByteArray. 10 | */ 11 | public class ByteDataStream extends ByteArray implements IDataStream { 12 | 13 | private var _dispatcher:IEventDispatcher; 14 | private var _connected:Boolean; 15 | 16 | /** 17 | * Create a new stream. 18 | */ 19 | public function ByteDataStream() { 20 | _dispatcher = new EventDispatcher(); 21 | } 22 | 23 | /** 24 | * @inheritDoc 25 | */ 26 | public function readCString():String { 27 | return IOUtil.readCString(this); 28 | } 29 | 30 | /** 31 | * @inheritDoc 32 | */ 33 | public function writeCString(value:String):void { 34 | IOUtil.writeCString(this, value); 35 | } 36 | 37 | /** 38 | * @inheritDoc 39 | */ 40 | public function dispatchEvent(event:Event):Boolean { 41 | return _dispatcher.dispatchEvent(event); 42 | } 43 | 44 | /** 45 | * @inheritDoc 46 | */ 47 | public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void { 48 | _dispatcher.removeEventListener(type, listener, useCapture); 49 | } 50 | 51 | /** 52 | * @inheritDoc 53 | */ 54 | public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void { 55 | _dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference); 56 | } 57 | 58 | /** 59 | * @inheritDoc 60 | */ 61 | public function hasEventListener(type:String):Boolean { 62 | return _dispatcher.hasEventListener(type); 63 | } 64 | 65 | /** 66 | * @inheritDoc 67 | */ 68 | public function willTrigger(type:String):Boolean { 69 | return _dispatcher.willTrigger(type); 70 | } 71 | 72 | /** 73 | * @inheritDoc 74 | */ 75 | public function flush():void { 76 | /* do nothing */ 77 | dispatchEvent(new DataStreamEvent(DataStreamEvent.PROGRESS)); 78 | } 79 | 80 | /** 81 | * @inheritDoc 82 | */ 83 | public function close():void { 84 | _connected = false; 85 | } 86 | 87 | /** 88 | * @inheritDoc 89 | */ 90 | public function get connected():Boolean { 91 | return _connected; 92 | } 93 | 94 | } 95 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/impl/ExtendedQueryHandler.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db.impl { 2 | import org.postgresql.EncodingFormat; 3 | import org.postgresql.Oid; 4 | import org.postgresql.codec.CodecFactory; 5 | import org.postgresql.codec.IPGTypeEncoder; 6 | import org.postgresql.db.IResultHandler; 7 | import org.postgresql.febe.ArgumentInfo; 8 | import org.postgresql.febe.IExtendedQueryHandler; 9 | import org.postgresql.io.ByteDataStream; 10 | import org.postgresql.util.getType; 11 | 12 | /** 13 | * Default implementation of IExtendedQueryHandler. 14 | */ 15 | public class ExtendedQueryHandler extends SimpleQueryHandler implements IExtendedQueryHandler { 16 | 17 | /** 18 | * Constructor. 19 | * 20 | * @param resultHandler result handler to pass results to 21 | * @param codecs codec factory for parameter encoding 22 | */ 23 | public function ExtendedQueryHandler(resultHandler:IResultHandler, codecs:CodecFactory) { 24 | super(resultHandler, codecs); 25 | } 26 | 27 | /** 28 | * Describe arguments by using the CodecFactory. Parameters are always encoded 29 | * in TEXT mode for symmetry with decoding. 30 | */ 31 | public function describeArguments(params:Array, serverParams:Object):Array { 32 | var encodedArgs:Array = []; 33 | for each (var arg:Object in params) { 34 | var argInfo:ArgumentInfo; 35 | if (arg == null) { 36 | argInfo = new ArgumentInfo(EncodingFormat.TEXT, Oid.UNSPECIFIED, null); 37 | } else { 38 | var argType:Class = getType(arg); 39 | var argEncoder:IPGTypeEncoder = _codecFactory.getEncoder(argType); 40 | var argOid:int = argEncoder.getInputOid(argType); 41 | var encodedValue:ByteDataStream = new ByteDataStream(); 42 | 43 | argEncoder.encode(encodedValue, arg, EncodingFormat.TEXT, serverParams); 44 | argInfo = new ArgumentInfo(EncodingFormat.TEXT, argOid, encodedValue); 45 | } 46 | encodedArgs.push(argInfo); 47 | } 48 | return encodedArgs; 49 | } 50 | 51 | /** 52 | * Always request output in TEXT mode. Since text handlers are already 53 | * required for the simple query protocol, and since choosing this per-type is too complex 54 | * (the driver would need to know the number of columns before executing the query or 55 | * require an extra round trip), TEXT is a reasonable choice. 56 | */ 57 | public function getOutputFormats(fieldDescriptions:Array):Array { 58 | return [ EncodingFormat.TEXT ]; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/EventResultHandler.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db { 2 | 3 | import org.postgresql.db.event.QueryResultEvent; 4 | import org.postgresql.db.event.QueryCompletionEvent; 5 | import flash.events.Event; 6 | import flash.events.IEventDispatcher; 7 | import flash.events.EventDispatcher; 8 | 9 | 10 | /** 11 | * Dispatched when a query completes. 12 | * 13 | * @eventType org.postgresql.db.event.QueryCompletionEvent 14 | */ 15 | [Event(name="queryCompletion", type="org.postgresql.db.event.QueryCompletionEvent")] 16 | 17 | /** 18 | * Dispatched when a query result set is available. 19 | * 20 | * @eventType org.postgresql.db.event.QueryResultEvent.RESULT 21 | */ 22 | [Event(name="queryResult", type="org.postgresql.db.event.QueryResultEvent")] 23 | 24 | /** 25 | * An IResultHandler which dispatches events when queries complete. 26 | */ 27 | public class EventResultHandler extends ResultHandlerBase implements IEventDispatcher { 28 | 29 | private var _dispatcher:IEventDispatcher; 30 | 31 | /** 32 | * @private 33 | */ 34 | public function EventResultHandler() { 35 | _dispatcher = new EventDispatcher(); 36 | } 37 | 38 | /** 39 | * @private 40 | */ 41 | public override function handleCompletion(command:String, rows:int, oid:int):void { 42 | if (columns) { 43 | _dispatcher.dispatchEvent(new QueryResultEvent(QueryResultEvent.RESULT, columns, data)); 44 | } 45 | _dispatcher.dispatchEvent(new QueryCompletionEvent(QueryCompletionEvent.COMPLETE, command, rows, oid)); 46 | } 47 | 48 | /** 49 | * @private 50 | */ 51 | public function dispatchEvent(event:Event):Boolean { 52 | return _dispatcher.dispatchEvent(event); 53 | } 54 | 55 | /** 56 | * @inheritDoc 57 | */ 58 | public function hasEventListener(type:String):Boolean { 59 | return _dispatcher.hasEventListener(type); 60 | } 61 | 62 | /** 63 | * @inheritDoc 64 | */ 65 | public function willTrigger(type:String):Boolean { 66 | return _dispatcher.willTrigger(type); 67 | } 68 | 69 | /** 70 | * @inheritDoc 71 | */ 72 | public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void { 73 | _dispatcher.removeEventListener(type, listener, useCapture); 74 | } 75 | 76 | /** 77 | * @inheritDoc 78 | */ 79 | public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void { 80 | _dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/SocketDataStream.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | import flash.events.ErrorEvent; 4 | import flash.events.Event; 5 | import flash.events.IOErrorEvent; 6 | import flash.events.ProgressEvent; 7 | import flash.events.SecurityErrorEvent; 8 | import flash.net.Socket; 9 | 10 | /** 11 | * A Socket-based implementation of IDataStream. The Socket 12 | * is connected immediately, and in normal operation, the server is 13 | * never expected to close the connection, so a simple close is considered 14 | * an error unless initiated by the client. 15 | * 16 | * @see flash.net.Socket 17 | */ 18 | public class SocketDataStream extends Socket implements IDataStream { 19 | 20 | private var _clientDisconnect:Boolean; 21 | 22 | /** 23 | * Create a new stream connecting to given host and port 24 | * 25 | * @param host host to connect to 26 | * @param port port to connect to 27 | */ 28 | public function SocketDataStream(host:String, port:int) { 29 | super(host, port); 30 | // TODO: Technically, if SocketDataStream "is a" socket, we should 31 | // support reconnect. Since we'll only be using it through the 32 | // IDataStream interface, we can be a little lazy here... 33 | _clientDisconnect = false; 34 | addEventListener(ProgressEvent.SOCKET_DATA, handleSocketData); 35 | addEventListener(IOErrorEvent.IO_ERROR, handleError); 36 | addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleError); 37 | addEventListener(Event.CLOSE, handleClose); 38 | } 39 | 40 | private function handleSocketData(e:ProgressEvent):void { 41 | if (connected) { 42 | dispatchEvent(new DataStreamEvent(DataStreamEvent.PROGRESS)); 43 | } 44 | } 45 | 46 | private function handleError(e:ErrorEvent):void { 47 | dispatchEvent(new DataStreamErrorEvent(DataStreamErrorEvent.ERROR, e.text)); 48 | } 49 | 50 | private function handleClose(e:Event):void { 51 | if (!_clientDisconnect) { 52 | dispatchEvent(new DataStreamErrorEvent(DataStreamErrorEvent.ERROR, "Unexpected close of stream by server")); 53 | } 54 | } 55 | 56 | /** 57 | * @inheritDoc 58 | */ 59 | public function readCString():String { 60 | return IOUtil.readCString(this); 61 | } 62 | 63 | /** 64 | * @inheritDoc 65 | */ 66 | public function writeCString(value:String):void { 67 | IOUtil.writeCString(this, value); 68 | } 69 | 70 | /** 71 | * @inheritDoc 72 | */ 73 | public override function close():void { 74 | _clientDisconnect = true; 75 | super.close(); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/io/IDataStream.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.io { 2 | 3 | import flash.events.IEventDispatcher; 4 | 5 | /** 6 | * Dispatched when new data is available in the stream. 7 | * 8 | * @eventType org.postgresql.io.DataStreamEvent.PROGRESS 9 | */ 10 | [Event(name="progress", type="org.postgresql.io.DataStreamEvent")] 11 | 12 | /** 13 | * Dispatched when an error occurs in the stream. After an error occurs, 14 | * the stream is in a disconnected state (and cannot be reconnected). 15 | * If ability to reconnect is integral to a client of an IDataStream, 16 | * an IDataStream factory should be used instead. (In that case, 17 | * a new stream can be obtained, effectively mimicing reconnection.) 18 | * 19 | * @eventType org.postgresql.io.DataStreamErrorEvent.ERROR 20 | */ 21 | [Event(name="dataStreamError", type="org.postgresql.io.DataStreamErrorEvent")] 22 | 23 | /** 24 | * Defines a binary communication channel between a client (using this stream) 25 | * and a server. The client initiates the connection, communicates with the 26 | * server using an established protocol, and then closes a connection. Data 27 | * can be written to or read from the stream. 28 | *
29 | * Note that a server is never expected to initiate close-of-stream in normal 30 | * operation, so no standard "IDataStream closed" event exists. A 31 | * standard server-initiated disconnection is considered an error. A client-initiated 32 | * close triggers a best-effort attempt to close the server connection cleanly, but 33 | * any failures here are ignored. 34 | *
35 | * Note that an IDataStream always connects automatically (technically, 36 | * the first time the AVM processes network requests after the constructor is 37 | * called), and cannot be reconnected once disconnected (whether through client 38 | * code or a server error. If finer control over connectivity is required, a 39 | * factory should be used. 40 | */ 41 | public interface IDataStream extends ICDataInput, ICDataOutput, IEventDispatcher { 42 | 43 | /** 44 | * Flush all pending client writes to the server. 45 | * 46 | * @throws flash.utils.Error if the connection is closed or broken 47 | */ 48 | function flush():void; 49 | 50 | /** 51 | * Close the connection to the backend. 52 | * 53 | * @throws flash.utils.Error if the connection is already closed or broken 54 | */ 55 | function close():void; 56 | 57 | /** 58 | * Connection status of stream. Note that a stream can be disconnected either 59 | * through client action or an error. 60 | * 61 | * @returns true if this stream is still connected; false otherwise 62 | */ 63 | function get connected():Boolean; 64 | } 65 | } -------------------------------------------------------------------------------- /pgconsole/src/org/postgresql/pgconsole/component/NoticeRenderer.mxml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /driver/src/org/postgresql/db/CallbackResultHandler.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.db { 2 | 3 | /** 4 | * An IResultHandler which invokes user-supplied callbacks when 5 | * query results are returned and on query completion. 6 | */ 7 | public class CallbackResultHandler extends ResultHandlerBase { 8 | 9 | private var _onCompletion:Function; 10 | private var _onQueryResult:Function; 11 | 12 | /** 13 | * Create a new CallbackResultHandler with specified callbacks. 14 | * The onQueryCompletion callback is required and should have the 15 | * following signature: 16 | *

17 |          * function(command:String, affectedRows:int):void
18 |          * 
19 | * where command is the PotsgreSQL command tag for the given query 20 | * (e.g., SELECT or INSERT) and affectedRows 21 | * is the number of rows affected if an update was performed (note that this is 22 | * not the number of rows returned). 23 | *
24 | * The onQueryResult callback is optional and should have the 25 | * following signature: 26 | *
27 |          * function(columns:Array, data:Array):void
28 |          * 
29 | * where columns is an array of IColumn objects defining the 30 | * fields returned and data is an array of Objects, each 31 | * representing a row with keys (property names) defined by the IColumn 32 | * objects and values corresponding to row values. 33 | *
34 | * If specified, the query result handler is invoked before the query completion 35 | * handler. Note that for a query with multiple statements, these may be invoked 36 | * multiple times. 37 | * 38 | * @param onCompletion query completion callback 39 | * @param onQueryResult query result callback 40 | * @see org.postgresql.db.IColumn 41 | */ 42 | public function CallbackResultHandler(onCompletion:Function, onQueryResult:Function=null) { 43 | if (onCompletion == null) { 44 | throw new ArgumentError("Completion handler cannot be null"); 45 | } 46 | _onQueryResult = onQueryResult; 47 | _onCompletion = onCompletion; 48 | } 49 | 50 | /** 51 | * @private 52 | */ 53 | public override function doHandleCompletion(command:String, rows:int, oid:int):void { 54 | if (columns) { 55 | onQueryResult(columns, data); 56 | } 57 | onCompletion(command, rows); 58 | } 59 | 60 | /** 61 | * @private 62 | * Invokes the onQueryResult callback. 63 | */ 64 | protected function onQueryResult(columns:Array, data:Array):void { 65 | if (_onQueryResult != null) { 66 | _onQueryResult(columns, data); 67 | } 68 | } 69 | 70 | /** 71 | * @private 72 | * Invokes the onCompletion callback. 73 | */ 74 | protected function onCompletion(command:String, rows:int):void { 75 | _onCompletion(command, rows); 76 | } 77 | 78 | } 79 | } -------------------------------------------------------------------------------- /test/src/org/postgresql/pegasus/util/TestDateFormatter.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.pegasus.util { 2 | import org.flexunit.Assert; 3 | import org.postgresql.util.DateFormatter; 4 | 5 | [RunWith("org.flexunit.runners.Parameterized")] 6 | public class TestDateFormatter { 7 | 8 | private var _formatter:DateFormatter; 9 | 10 | [Before] 11 | public function setup():void { 12 | _formatter = new DateFormatter(); 13 | } 14 | 15 | public static function getTestDates():Array { 16 | return [ 17 | // N.B.: the month is zero-indexed in the Date constructor 18 | [ new Date(2134, 4, 6, 7, 8, 9), 'YY', '34' ], 19 | [ new Date(2134, 4, 6, 7, 8, 9), 'YYYY', '2134' ], 20 | [ new Date(2134, 4, 6, 7, 8, 9), 'M', '5' ], 21 | [ new Date(2134, 9, 6, 7, 8, 9), 'M', '10' ], 22 | [ new Date(2134, 4, 6, 7, 8, 9), 'MM', '05' ], 23 | [ new Date(2134, 9, 6, 7, 8, 9), 'MM', '10' ], 24 | [ new Date(2134, 5, 6, 7, 8, 9), 'MMM', 'Jun' ], 25 | [ new Date(2134, 3, 6, 7, 8, 9), 'MMMM', 'April' ], 26 | [ new Date(2134, 4, 6, 7, 8, 9), 'D', '6' ], 27 | [ new Date(2134, 4, 26, 7, 8, 9), 'D', '26' ], 28 | [ new Date(2134, 4, 6, 7, 8, 9), 'DD', '06' ], 29 | [ new Date(2134, 4, 26, 7, 8, 9), 'DD', '26' ], 30 | [ new Date(2134, 4, 6, 7, 8, 9), 'J', '7' ], 31 | [ new Date(2134, 4, 6, 17, 8, 9), 'J', '17' ], 32 | [ new Date(2134, 4, 6, 7, 8, 9), 'JJ', '07' ], 33 | [ new Date(2134, 4, 6, 17, 8, 9), 'JJ', '17' ], 34 | [ new Date(2134, 4, 6, 7, 8, 9), 'N', '8' ], 35 | [ new Date(2134, 4, 6, 7, 18, 9), 'N', '18' ], 36 | [ new Date(2134, 4, 6, 7, 8, 9), 'NN', '08' ], 37 | [ new Date(2134, 4, 6, 7, 18, 9), 'NN', '18' ], 38 | [ new Date(2134, 4, 6, 7, 8, 9), 'S', '9' ], 39 | [ new Date(2134, 4, 6, 7, 18, 19), 'S', '19' ], 40 | [ new Date(2134, 4, 6, 7, 8, 9), 'SS', '09' ], 41 | [ new Date(2134, 4, 6, 7, 18, 19), 'SS', '19' ], 42 | [ new Date(2134, 4, 6, 7, 8, 0, 9), 'Q', '9' ], 43 | [ new Date(2134, 4, 6, 7, 18, 0, 19), 'Q', '19' ], 44 | [ new Date(2134, 4, 6, 7, 18, 0, 192), 'Q', '192' ], 45 | [ new Date(2134, 4, 6, 7, 8, 0, 9), 'QQ', '09' ], 46 | [ new Date(2134, 4, 6, 7, 18, 0, 19), 'QQ', '19' ], 47 | [ new Date(2134, 4, 6, 7, 18, 0, 192), 'QQ', '192' ], 48 | [ new Date(2134, 4, 6, 7, 8, 0, 9), 'QQQ', '009' ], 49 | [ new Date(2134, 4, 6, 7, 18, 0, 19), 'QQQ', '019' ], 50 | [ new Date(2134, 4, 6, 7, 18, 0, 192), 'QQQ', '192' ], 51 | [ new Date(2134, 4, 6, 7, 8, 9, 555), 'YYYY-MM-DD JJ:NN:SS.QQQ', '2134-05-06 07:08:09.555' ], 52 | [ new Date(2134, 4, 6, 7, 8, 9, 555), '\\Y\\Y\\Y\\Y-\\M\\M-\\D\\D \\J\\J:\\N\\N:\\S\\S.\\Q\\Q\\Q', 'YYYY-MM-DD JJ:NN:SS.QQQ' ] 53 | ]; 54 | } 55 | 56 | [Test(dataProvider="getTestDates")] 57 | public function testFormatDate(date:Date, formatString:String, expected:String):void { 58 | _formatter.formatString = formatString; 59 | var result:String = _formatter.format(date); 60 | Assert.assertEquals(expected, result); 61 | } 62 | 63 | } 64 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/codec/decode/FloatOut.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.codec.decode { 2 | 3 | import org.postgresql.EncodingFormat; 4 | import org.postgresql.Oid; 5 | import org.postgresql.codec.IPGTypeDecoder; 6 | import org.postgresql.febe.IFieldInfo; 7 | import org.postgresql.io.ICDataInput; 8 | 9 | /** 10 | * Parse a PostgreSQL double precision or float value into 11 | * an ActionScript Number. Since both support IEEE floating point numbers, 12 | * the mapping is fairly straightforward, albeit it depends on the extra_float_digits 13 | * PostgreSQL setting. 14 | */ 15 | public class FloatOut implements IPGTypeDecoder { 16 | 17 | // This is an interesting tidbit of IEEE fun... Due to the default precision PostgreSQL 18 | // uses when printing doubles in text mode, the textual representation of the largest double 19 | // is a value rounded to something *bigger* than the largest double (and, correspondingly, Number). 20 | // Hilarity ensues. This is the sober workaround to that rampant hilarity. A better solution 21 | // would be to work with extra_float_digits, but it's a little ugly to force that. Perhaps we 22 | // can set it but fall back if it's subsequently changed. 23 | private static const MAX_PG_DOUBLE_STR:String = "1.79769313486232e+308"; 24 | 25 | /** 26 | * @inheritDoc 27 | */ 28 | public function decode(bytes:ICDataInput, format:IFieldInfo, serverParams:Object):Object { 29 | switch (format.format) { 30 | case EncodingFormat.TEXT: 31 | // Note that this also parses 'Infinity', '-Infinity', and 'NaN' 32 | var resultStr:String = bytes.readUTFBytes(bytes.bytesAvailable); 33 | var result:Number = Number(resultStr); 34 | // As noted above, PostgreSQL formats the largest double into something that the 35 | // Number() function treats as Infinity. So if it's not finite, not NaN (because 36 | // NaN is considered "not finite"), and matches the string above, we treat it as 37 | // Number.MAX_VALUE (modulo sign); otherwise, we just return what Number() gave. 38 | // Unfortunately, this approach only works for the default extra_float_digits setting. 39 | if (!isFinite(result) && !isNaN(result) && resultStr.indexOf(MAX_PG_DOUBLE_STR) != -1) { 40 | return result > 0 ? Number.MAX_VALUE : -Number.MAX_VALUE; 41 | } else { 42 | return result; 43 | } 44 | case EncodingFormat.BINARY: 45 | switch (format.typeOid) { 46 | // N.B.: We could theoretically support numerics that are expressible 47 | // as floats, but that's probably not worth it right now 48 | case Oid.FLOAT4: 49 | return bytes.readFloat(); 50 | case Oid.FLOAT8: 51 | return bytes.readDouble(); 52 | default: 53 | throw new ArgumentError("Unable to decode oid: " + format.typeOid); 54 | } 55 | default: 56 | throw new ArgumentError("Unknown format: " + format.format); 57 | } 58 | } 59 | 60 | /** 61 | * This decoder returns Number. 62 | * @see Number 63 | */ 64 | public function getOutputClass(typeOid:int):Class { 65 | return Number; 66 | } 67 | 68 | } 69 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/DateStyle.as: -------------------------------------------------------------------------------- 1 | package org.postgresql { 2 | 3 | /** 4 | * Functionality defining the representation of dates in PostgreSQL. 5 | */ 6 | public class DateStyle { 7 | /** 8 | * Expect dates in ISO-8601 format, e.g., 2011-02-01 18:53:12.848059-08. 9 | */ 10 | public static const OUTPUT_ISO:String = 'ISO'; 11 | /** 12 | * Expect dates in a legacy format, e.g., Tue 01 Feb 18:54:14.348079 2011 PST. 13 | * Note that this output format is also affected by the MDY part of the DateStyle 14 | * setting: when set to DMY, the day is printed first. 15 | */ 16 | public static const OUTPUT_POSTGRES:String = 'Postgres'; 17 | /** 18 | * Expect dates in SQL standard format, e.g., 01/02/2011 18:56:05.379808 PST. 19 | * Note that this output format is also affected by the MDY part of the DateStyle 20 | * setting: when set to DMY, the day is printed first. 21 | */ 22 | public static const OUTPUT_SQL:String = 'SQL'; 23 | /** 24 | * Expect dates in a custom legacy format, e.g., 01.02.2011 18:55:23.025107 PST. 25 | */ 26 | public static const OUTPUT_GERMAN:String = 'German'; 27 | 28 | /** 29 | * Parse timestamp literals in the order month, day, year. E.g., 30 | * SELECT '10/11/12'::timestamp will produce October 11th, 2012. 31 | */ 32 | public static const ORDER_MDY:String = 'MDY'; 33 | /** 34 | * Parse timestamp literals in the order day, month, year. E.g., 35 | * SELECT '10/11/12'::timestamp will produce November 10th, 2012. 36 | */ 37 | public static const ORDER_DMY:String = 'DMY'; 38 | /** 39 | * Parse timestamp literals in the order day, month, year. E.g., 40 | * SELECT '10/11/12'::timestamp will produce November 12th, 2010. 41 | */ 42 | public static const ORDER_YMD:String = 'YMD'; 43 | 44 | /** 45 | * Get the current setting for parsing day/month/year timestamp literals 46 | * from a DateStyle value. The possible values are denoted by 47 | * the constants in this class. 48 | * 49 | * @param value a DateStyle string returned by the server 50 | * @return the specified day/month/year order 51 | * @see #ORDER_MDY 52 | * @see #ORDER_DMY 53 | * @see #ORDER_YMD 54 | */ 55 | public static function getDMYOrder(value:String):String { 56 | return parse(value)[1]; 57 | } 58 | 59 | /** 60 | * Get the current setting for date output format from a DateStyle 61 | * value. The possible values are denoted by the constants in this class. 62 | * 63 | * @param value a DateStyle string returned by the server 64 | * @return the specified output format style 65 | * @see #OUTPUT_ISO 66 | * @see #OUTPUT_POSTGRES 67 | * @see #OUTPUT_SQL 68 | * @see #OUTPUT_GERMAN 69 | */ 70 | public static function getOutputFormat(value:String):String { 71 | return parse(value)[0]; 72 | } 73 | 74 | /** 75 | * @private 76 | */ 77 | private static function parse(value:String):Array { 78 | var result:Array = value.split(', '); 79 | if (result.length != 2) { 80 | throw new ArgumentError("Invalid DateStyle string: " + value); 81 | } else { 82 | return result; 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /driver/src/org/postgresql/febe/IConnectionHandler.as: -------------------------------------------------------------------------------- 1 | package org.postgresql.febe { 2 | 3 | import org.postgresql.CodecError; 4 | import org.postgresql.ProtocolError; 5 | 6 | /** 7 | * Provides callbacks for interactions with the PostgreSQL protocol-level 8 | * connection object. In terms of the interface contract, "query" means 9 | * any message sent to the server through the basic or extend query protocol. 10 | */ 11 | public interface IConnectionHandler { 12 | 13 | /** 14 | * Indicates a warning or other notice. The connection is still live. 15 | * 16 | * @param fields fields defining notice 17 | * @see org.postgresql.NoticeFields 18 | */ 19 | function handleNotice(fields:Object):void; 20 | 21 | // N.B.: Technically, this is also how the server communicates protocol 22 | // errors such as "wtf are you talking about, client?" However, if the 23 | // driver is doing its job, that won't happen, so we will not expose 24 | // this in the interface 25 | // 26 | /** 27 | * Indicates an SQL or authentication error. The connection may or may 28 | * not be live. If the connection has been broken, this call will be followed 29 | * by one of the other calls below, but note that the connection may 30 | * already be down when this callback is running. 31 | * 32 | * @param fields fields defining the error 33 | * @see org.postgresql.NoticeFields 34 | */ 35 | function handleSQLError(fields:Object):void; 36 | 37 | /** 38 | * Indicates an error in encoding or decoding. The connection is still live, 39 | * but the current query has been discarded. 40 | * 41 | * @param error CodecError describing the issue 42 | */ 43 | function handleCodecError(error:CodecError):void; 44 | 45 | /** 46 | * Indicates an error in the understanding of the protocol between client 47 | * and server. The connection is broken. 48 | * 49 | * @param error ProtocolError describing the issue 50 | */ 51 | function handleProtocolError(error:ProtocolError):void; 52 | 53 | /** 54 | * Indicates a connectivity error in the underlying stream. The connection 55 | * is broken. 56 | * 57 | * @param error Error describing the issue 58 | */ 59 | function handleStreamError(error:Error):void; 60 | 61 | // TODO: for PG 9+, this can include a (string) payload 62 | /** 63 | * Indicates a PostgreSQL LISTEN / NOTIFY notification. 64 | * 65 | * @param condition LISTEN condition 66 | * @param notifierPid process identifier of the notifying process 67 | */ 68 | function handleNotification(condition:String, notifierPid:int):void; 69 | 70 | /** 71 | * Indicates that a query has finished executing and that the underlying 72 | * connection is ready for another query. 73 | * 74 | * @param status the current transaction status 75 | * @see org.postgresql.TransactionStatus 76 | */ 77 | function handleReady(status:String):void; 78 | 79 | /** 80 | * Indicates that the underlying connection has completed the handshake 81 | * with the backend and the connection is ready for use. 82 | */ 83 | function handleConnected():void; 84 | 85 | /** 86 | * Indicates a change to a server parameter. Note that a number of parameter 87 | * "changes" occur at startup to communicate the server's initial parameter 88 | * values. 89 | * 90 | * @param name parameter which has changed 91 | * @param newValue the new value 92 | */ 93 | function handleParameterChange(name:String, newValue:String):void; 94 | } 95 | } --------------------------------------------------------------------------------