├── 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 | 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 | 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 | 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 | *
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 | 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 | 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 | [ 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 | * 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 | * 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 | 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 | * 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 | * 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 | * 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 | * 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 | 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 | 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 | * 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 | * 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 | 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 | * 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 | * 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 | }
--------------------------------------------------------------------------------